链接:https://www.nowcoder.com/questionTerminal/4bc284dc9d0144628a722eb5d1191ef3?answerType=1&f=discussion
来源:牛客网
给出一个数字N(0<N<1000000),将N写成立方数和的形式,求出需要的最少立方数个数。
例如N=17,1+8+8 = 17,最少需要3个立方数,则输出3。
N= 28,1+1+1+1+8+8+8=28, 需要7个立方数,1+27=28,需要2个立方数,所以最少立方数为2,则输出2。
输入描述:
一个数字N(0<N<1000000)
输出描述:
最少立方数个数
示例1
输入
28
输出
2
https://www.nowcoder.com/practice/4bc284dc9d0144628a722eb5d1191ef3?tpId=125&&tqId=33735&rp=1&ru=/activity/oj&qru=/ta/exam-xiaomi/question-ranking
数字 N N N,可以把 N N N分解成若干个立方数相加
如 : 17 = 1 + 8 + 8, 28 = 1+1+1+1+ 8 + 8 + 8
给定 N N N,问最少可以分解成几个数
-
n n n的子问题是
- n − 1 ∗ 1 ∗ 1 n-1 * 1 * 1 n−1∗1∗1
- n − 2 ∗ 2 ∗ 2 n-2 * 2 * 2 n−2∗2∗2
- n − 3 ∗ 3 ∗ 3 n - 3 * 3 * 3 n−3∗3∗3
- . . . . . ..... .....
- n − k ∗ k ∗ k 且 ( k ∗ k ∗ k < = n ) n-k * k *k~~~且(k * k * k <=n) n−k∗k∗k 且(k∗k∗k<=n)
-
所以 n n n的答案就是从子问题里选最小
d p ( n ) = m i n ( a n s n , d p ( n − k ∗ k ∗ k ) + 1 ) dp(n) = min(ans_n, dp(n-k * k * k)+1) dp(n)=min(ansn,dp(n−k∗k∗k)+1)
int mem[MAXN]; int dp(int n) { if(n <= 0) return 0; if(INF != mem[n]) return mem[n]; int i = 1; while(i*i*i <= n) { mem[n] = min(mem[n], dp(n-i*i*i)+1); i ++; } return mem[n]; }
动态规划解法
memset(dp, INF, sizeof(dp));
dp[0] = 0; //边界条件为dp[0] = 0;
for(int i=1; i<=n; i++)
for(int j=1; j*j*j<=i; j++)
dp[i] = min(dp[i], dp[i-j*j*j]+1);
cout << dp[n] << endl;
完整代码
#define debug
#ifdef debug
#include <time.h>
#include "/home/majiao/mb.h"
#endif
#include <iostream>
#include <algorithm>
#include <vector>
#include <string.h>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <math.h>
#define MAXN ((int)1e6+7)
#define ll long long
#define INF (0x7f7f7f7f)
#define fori(lef, rig) for(int i=lef; i<=rig; i++)
#define forj(lef, rig) for(int j=lef; j<=rig; j++)
#define fork(lef, rig) for(int k=lef; k<=rig; k++)
#define QAQ (0)
using namespace std;
#define show(x...) \
do { \
cout << "\033[31;1m " << #x << " -> "; \
err(x); \
} while (0)
void err() { cout << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cout << a << ' '; err(x...); }
namespace FastIO {
char print_f[105];
void read() { }
void print() { putchar('\n'); }
template <typename T, typename... T2>
inline void read(T &x, T2 &... oth) {
x = 0;
char ch = getchar();
ll f = 1;
while (!isdigit(ch)) {
if (ch == '-') f *= -1;
ch = getchar();
}
while (isdigit(ch)) {
x = x * 10 + ch - 48;
ch = getchar();
}
x *= f;
read(oth...);
}
template <typename T, typename... T2>
inline void print(T x, T2... oth) {
ll p3=-1;
if(x<0) putchar('-'), x=-x;
do{
print_f[++p3] = x%10 + 48;
} while(x/=10);
while(p3>=0) putchar(print_f[p3--]);
putchar(' ');
print(oth...);
}
} // namespace FastIO
using FastIO::print;
using FastIO::read;
int mem[MAXN];
int dp(int n) {
if(n <= 0) return 0;
if(INF != mem[n]) return mem[n];
int i = 1;
while(i*i*i <= n) {
mem[n] = min(mem[n], dp(n-i*i*i)+1);
i ++;
}
return mem[n];
}
int main() {
#ifdef debug
freopen("test", "r", stdin);
// freopen("out_main", "w", stdout);
clock_t stime = clock();
#endif
int n;
cin >> n;
memset(mem, INF, sizeof(mem));
int ans = dp(n);
cout << ans << endl;
#ifdef debug
clock_t etime = clock();
printf("rum time: %lf 秒\n",(double) (etime-stime)/CLOCKS_PER_SEC);
#endif
return 0;
}