いわゆる、重複ありのナップサック問題
問題概要
整数 を最小個数の四面体数 (重複あり) の和として表せ。
解法
四面体数は、mC3 の形で表される。
重複ありのナップサックも、うまくやれば、種類数の線形オーダーで効率的に解けることの練習。
#include <iostream> #include <vector> using namespace std; const int MAX = 1000100; const int INF = 1<<29; int main() { vector<int> dp(MAX, INF), odddp(MAX, INF); dp[0] = odddp[0] = 0; for (int i = 1;; ++i) { int num = i * (i+1) * (i+2) / 6; if (num >= MAX) break; for (int j = num; j < MAX; ++j) { dp[j] = min(dp[j], dp[j-num]+1); if (num & 1) odddp[j] = min(odddp[j], odddp[j-num]+1); } } int n; while (cin >> n) { if (n == 0) break; cout << dp[n] << " " << odddp[n] << endl; } }