Codeforces Gym 101164I Cubes

Problem I
Cubes
Input File: I.in
Output File: standard output
Time Limit: 0.5 seconds (C/C++)
Memory Limit: 256 megabytes
Write a program that takes a natural number N and decomposes it as a sum of the minimum number of
exact natural cubes. The program should find
m1, m2, …, mk, such that each mi is a natural number,
m1
3
+ m23 +… + mk3 = N, and k is minimal.
Input
The only line of the input file contains the number N (1 ≤ N ≤ 44,777,444).
Output
Your program should write exactly two lines. The first line contains the number k - the minimum
number of natural cubes. The second line contains
k space-separated natural numbers - that
raised to the power of 3 sum to
N.

Sample input Sample output
42 7
2 2 2 2 2 1 1
43 3
3 2 2

题目大意:给定一个数n,要求将n分成k个数的立方和,使得k最小。

思路:该题有多种做法,可以采用BFS的方法,也可以采用DFS的方法。

BFS:

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<queue>

using namespace std;

const int MAXN=50000010;
int dis[MAXN];
int ans[1000];
queue <int> q;
bool p;
int work(int n,int required,int MAX)
{
	if (dis[n]<1000 && !p)
	{
		return dis[n];	
	}
	if (!n)
	{
		return 0;
	}
	if (required<=2 && dis[n]>required)
	{
		return 3;
	}
	int ret=required+1;
	for (int i=MAX;i>=1;i--)
	{
		int m=n-i*i*i;
		if (m<0)
		{
			continue;
		}
		int res=work(m,required-1,i)+1;
		if (res<ret)
		{
			ans[required-1]=i;
			ret=res;
		}
		required=ret-1;	
	} 
	return ret;
}
int main()
{
	int n;
	scanf("%d",&n);
	for (int i=0;i<MAXN;i++)
	{
		dis[i]=1000;
	}
	q.push(0);
	dis[0]=0;
	while (!q.empty())
	{
		int x=q.front();
		if (dis[x]==3)
		{
			break;
		}
		q.pop();
		for (int i=1;x+i*i*i<MAXN;i++)
		{
			int y=x+i*i*i;
			if (dis[y]>dis[x]+1)
			{
				dis[y]=dis[x]+1;
				q.push(y);
			}
		}
	}
	int num=work(n,100,400);
	p=true;
	work(n,num,400);
	printf("%d\n",num);
	for (int i=0;i<num;i++)
	{
		printf("%d ",ans[i]);
	}
    return 0;
}

DFS:

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<ctime>

using namespace std;

const int MAXN=500;
int n,tot;
int p[MAXN];
int num[MAXN];
void dfs(int n,int i,int rem)
{
	if (n==0)
	{
		printf("%d\n",tot);
		for (int i=0;i<tot;i++)
		{
			printf("%d ",num[i]);
		}
		exit(0);
	}
	if (rem<=0)
	{
		return ;
	}
	int id=upper_bound(p+1,p+MAXN,n)-(p+1);
	i=min(i,id);
	if (n>p[i]*rem)
	{
		return ;
	}
	tot++;
	while (i>=1)
	{
		num[tot-1]=i;
		dfs(n-p[i],i,rem-1);
		i--;
	}
	tot--;
}
int main()
{
	for (int i=1;i<MAXN;i++)
	{
		p[i]=i*i*i;
	}
	scanf("%d",&n);
	for (int i=1;;i++)
	{
		dfs(n,MAXN-1,i);	
	} 
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值