dp[n] = 「正整数nを表すために必要な正四面体数の個数の最小」とする。この時、dp[n] = min(dp[n-1], dp[n-4], dp[n-10], ... , dp[n - (n以下である、正四面体数の最大)]) + 1となる。
奇数の場合も同様に考える。
#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int tri[182];
int squ[182];//181*182*183/6 = 1004731 > 10^6
#define MAX 1000000
int dp[MAX], dp_odd[MAX];
int n;
int main()
{
tri[0] = squ[0] = 0;
for (int i = 1; i < 182; i++)
tri[i] = tri[i-1] + i,
squ[i] = squ[i-1] + tri[i];
dp[0] = dp_odd[0] = 0;
for (int i = 1; i < MAX; i++) {
//少なくともsqu[1]=1をi個だけ用いて表せる。
dp[i] = dp_odd[i] = i;
for (int j = 1;; j++) {
int t = squ[j];
if (t > i) break;
dp[i] = min(dp[i], dp[i-t]+1);
if (t&1)
dp_odd[i] = min(dp_odd[i], dp_odd[i-t]+1);
}
}
while (cin >> n, n)
printf("%d %d\n", dp[n], dp_odd[n]);
return 0;
}