An addition chain for n is an integer sequence < a0, a1, a2, . . . , am > with the following four properties:
• a0 = 1
• am = n
• a0 < a1 < a2 < · · · < am−1 < am
• For each k (1 ≤ k ≤ m) there exist two (not neccessarily different) integers i and j (0 ≤ i, j ≤ k−1)
with ak = ai + aj
You are given an integer n. Your job is to construct an addition chain for n with minimal length.
If there is more than one such sequence, any one is acceptable.
For example, < 1, 2, 3, 5 > and < 1, 2, 4, 5 > are both valid solutions when you are asked for an
addition chain for 5.
Input
The input file will contain one or more test cases. Each test case consists of one line containing one
integer n (1 ≤ n ≤ 10000). Input is terminated by a value of zero (0) for n.
Output
For each test case, print one line containing the required integer sequence. Separate the numbers by
one blank.
Sample Input
5
7
12
15
77
0
Sample Output
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
分析一下题意,是给出一个数n,求从1到n的一个数列,要求这个数列是递增的,且数列中任意一个数都能表示为此数前的数的和。
例如:1 2 4 8 9 17 34 68 77中
2=1+1 4=2+2 8=4+4 9=8+1
以此类推,求最短的数列。
因为要求最短的数列,我们就立刻想到了BFS,但是观察范围1 ≤ n ≤ 10000,
每个节点存这么多,内存肯定要炸。于是又有童鞋想到了DFS,这个不会超内存的,但是超级费时间。所以,这道题,既不能用BFS,也不能直接用DFS。于是,万能的人类创造了IDDFS迭代加深搜索。
先整个循环,枚举数列的长度,从1开始,不断加深,直到能找到数列为止。
while(~scanf("%d",&n)&&n)//多组数据
{
ans[1]=1;//数列第一个数就是1
fl=0;//判断是否找到答案
for(deep=1;;deep++)//迭代加深的循环,deep为数列的长度
{
dfs(1,deep);
if(fl) break;//找到了就退出循环
}
for(int i=1;i<deep;i++)
printf("%d ",ans[i]);
printf("%d",ans[deep]);//有的OJ上判题很严,末尾不能有空格
printf("\n");//我就因空格而WA了一次
}
然后就是一个暴力的深搜。
注意:
1、数列长度到了就return,但fl不一定为true。
2、数列递增,所以要判断相加是否大于前一个。
3、优化1:里面枚举相加来得出新元素时,两个for要从大到小,且第二层for要从第一层的值开始,以免重复。(防TLE)
4、优化2:若当前这个数为x,还有y个数可以填,那么最大的那个数为x<<y,如果x<<y比n小,就直接可以跳过,该情况预处理为不存在。(防TLE)
void dfs(int x,int dep)//x为当前长度,dep为目标长度
{
if(x==dep){
if(ans[x]==n)
fl=1;//只有最后一个数等于n时才能结束
return;
}
if(fl) return;
for(int i=x;i>=1;i--)
{
for(int j=i;j>=1;j--)//优化1
{
if(ans[i]+ans[j]>ans[x])
{
ans[x+1]=ans[i]+ans[j];//处理下一个
if(ans[x+1]<<(dep-x-1)<n) continue;//优化2
dfs(x+1,dep);
if(fl) return;//防止多搜
}
}
}
}
感谢感谢,新手上路,多多指教。