ZOJ-1937 Addition Chains(迭代搜索)

/*
1937Addition Chains

--------------------------------------------------------------------------------

Time Limit: 1 Second      Memory Limit: 32768 KB      Special Judge

--------------------------------------------------------------------------------

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 necessarily 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 will contain one or more test cases. Each test case consists of one line containing one integer n (1 <= n <= 100). 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!的复杂度,用广度的话
找到的第一个加法链就是最短的,但是对空间占用太大
逐步深化的迭代搜索可以保证第一个找到的加法链就是最短的,又不需要太大的空间开销。
基本思想是控制回溯的搜索深度deep, 每次使deep加1,直到找到一条加法链

(更多优化):1.deep有一个下界,从此下界开始搜索,可以最大加快搜索进程
 2.更多剪枝
 3.最短加法链的上界,是一个幂树。
*/
#include <iostream>
using namespace std;
int n;
int v[50];
int re[50];
bool found;
int deep,best;
void dfs(int i)
{
    if(!found)
    {
        if(v[i]==n)
  {   
            best=i;
            for(int j=0;j<=i;++j)
                re[j]=v[j];
   found=true;
   return;
        }
        else if(i<deep)
            for(int j=i;j>=0;--j)
                if(v[j]*2>v[i])
                    for(int k=j;k>=0;--k)
                        if(v[j]+v[k]>v[i]&&v[j]+v[k]<=n)
                        {   
                            v[i+1]=v[j]+v[k];
                            dfs(i+1);
                        }                  
    }
}
int main()
{
    while(cin>>n&&n>0)
    {
  found=false;
  deep=2;best=n;
        while(!found)
        {
            v[0]=1;
            dfs(0);
            deep++;
        }
        for(int i=0;i<=best;++i)
            cout<<re[i]<<" ";
        cout<<endl;
  
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值