您的位置:首页 > 大数据 > 人工智能

ZOJ1937 Addition Chains

2018-10-08 14:16 465 查看

题目描述

原题来自:ZOJ 1937

已知一个数列 a0,a1...ama_0,a_1...a_ma0​,a1​...am​(其中 a0=1,am=n,a0<a1<a2<...<am−1<ama_0 = 1 , a_m = n , a_0 \lt a_1 \lt a_2 \lt ... \lt a_{m-1} \lt a_ma0​=1,am​=n,a0​<a1​<a2​<...<am−1​<am​)。对于每个 kkk,需要满足 ak=ai+aja_k=a_i+a_jak​=ai​+aj​(0≤i,j≤k−10 \leq i , j \leq k-10≤i,j≤k−1,这里 iii 与 jjj 可以相等)。

现给定 nnn 的值,要求 mmm 的最小值(并不要求输出),及这个数列每一项的值(可能存在多个数列,只输出任一个满足条件的就可以了)。

输入格式

多组数据,每行给定一个正整数 nnn 。

输入以 000 结束。

输出格式

对于每组数据,输出满足条件的长度最小的数列。

样例

样例输入

5
7
12
15
77
0

样例输出

1 2 4 5
1 2 4 6 7
1 2 4 8 12
1 2 4 5 10 15
1 2 4 8 9 17 34 68 77
很好玩的题,其实不用推什么公式,虽然数据范围是100
但是把搜索写好了,再加一点剪枝就可以
如果说有什么问题就是我们学校的数据锅了
下面给出代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
inline int rd(){
int x=0,f=1;
char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
int a[100000];
int book[100000];
int ans,n;
bool dfs(int step){
memset(book,0,sizeof(book));
if(step>ans){//剪枝,在长度超过我们所需的时候,判断是否已经完成
if(a[ans]==n) return 1;
return 0;
}
for(int i=step-1;i>=1;i--){
for(int j=i;j>=1;j--){//从i开始,因为可以重复
if(a[i]+a[j]>n) continue;//取的值必须严格小于n
if(!book[a[i]+a[j]]){//不能取重复的值,严格递增
if(a[i]+a[j]<=a[step-1]) return 0;
book[a[i]+a[j]]=1;
a[step]=a[i]+a[j];
int hh=a[step];
for(int k=step+1;k<=ans;k++) hh*=2;//如果取这个值在所限定的个数内取最大值也到不了,就不能取
if(hh<n) break;
if(dfs(step+1)) return 1;//递增长度,回溯
a[step]=0;
book[a[i]+a[j]]=0;
}
}
}
return 0;
}
int main(){
while(1){
memset(a,0,sizeof(a));
n=rd();
if(n==0) return 0;//因为长度小,所以要特判
else if(n==1){
printf("1\n");
continue;
}
else if(n==2){
printf("1 2\n");
continue;
}
a[1]=1;
a[2]=2;
for(ans=3;!dfs(3);ans++);//判断每个长度是否可行,否则加一
for(int i=1;i<ans;i++) printf("%d",a[i]);
printf("%d\n",a[ans]);
}
return 0;
}

 

 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: