牛客 小米 最少立方数之和 记忆化搜索

链接: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 n111
    • n − 2 ∗ 2 ∗ 2 n-2 * 2 * 2 n222
    • n − 3 ∗ 3 ∗ 3 n - 3 * 3 * 3 n333
    • . . . . . ..... .....
    • n − k ∗ k ∗ k     且 ( k ∗ k ∗ k < = n ) n-k * k *k~~~且(k * k * k <=n) nkkk   (kkk<=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(nkkk)+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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值