Problem I
Cubes
Input File: I.inOutput 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;
}