满足如下条件的序列X(序列中元素被标号为1、2、3…m)被称为“加成序列”:
1、X[1]=1
2、X[m]=n
3、X[1]<X[2]<…<X[m-1]<X[m]
4、对于每个 k(2≤k≤m)都存在两个整数 i 和 j (1≤i,j≤k−1,i 和 j 可相等),使得X[k]=X[i]+X[j]。
你的任务是:给定一个整数n,找出符合上述条件的长度m最小的“加成序列”。
如果有多个满足要求的答案,只需要找出任意一个可行解。
输入格式
输入包含多组测试用例。
每组测试用例占据一行,包含一个整数n。
当输入为单行的0时,表示输入结束。
输出格式
对于每个测试用例,输出一个满足需求的整数序列,数字之间用空格隔开。
每个输出占一行。
数据范围
1≤n≤100
输入样例:
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
题目链接:https://www.acwing.com/problem/content/description/172/
#include <iostream>
#include <vector>
#include <string.h>
using namespace std;
//迭代加深,DFS求最小值,只有两种方法,一:利用全局最小量然后搜索所有可能的结果。
//二: 使用迭代加深,搜索树有的节点很深,但是答案却很浅>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int n;
vector <int> v;
bool dfs(int u,int depth){ //当前深度为u
if(u == depth)
{
if(v[depth-1] == n) return true;
return false;
}
bool st[100]={false}; //3 序列的后半部分是4, 5, 6, 7, 8,那么4 + 7 = 5 + 6 > 8。
for(int i=u-1;i>=0;i--)
{
for(int j=i;j>=0;j--)
{
if(v[i] + v[j] > n ) continue; //剪枝1
if(v[i] + v[j] <= v[u-1]) continue; // 2
if(st[v[i] + v[j]]== true) continue; //表示这个和已经尝试过了
st[v[i]+v[j]] = true;
v.push_back(v[i]+v[j]);
if(dfs(u+1,depth) == true ) return true;
v.pop_back();
}
}
return false;
}
int main(int argc, char** argv) {
while(cin >> n , n!=0 )
{
v.clear();
int depth=1;
v.push_back(1);
while(true)
{
if(dfs(1,depth) == true) break;
depth++;
}
for(int i=0;i<v.size();i++)
{
cout << v[i];
if(i!=v.size()-1)
{
cout << " ";
}
}
cout << endl;
}
return 0;
}