Acwing 170 加成序列 (迭代加深搜尋)
阿新 • • 發佈:2020-07-21
題面
滿足如下條件的序列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
思路
我們要求的是一個最短長度的序列滿足他的條件,(遞增,首尾限定)。那麼我們根據它的資料量可以知道,這個搜尋的層數是很淺,呈指數遞減。所以我們迭代搜尋層數。
程式碼實現
#include<cstdio> #include<iostream> #include<queue> #include<cmath> #include<algorithm> #include<vector> #include<cstring> using namespace std; const int mod=998244353; const int maxn=110; int n; int a[maxn]; bool dfs (int u,int depth) { if (u==depth) return a[u-1]==n; bool vis[maxn]={false}; for (int i=u-1;i>=0;i--) for (int j=i;j>=0;j--) { int ans=a[i]+a[j]; if (ans<=n&&ans>=a[u-1]&&!vis[ans]) { vis[ans]=true; a[u]=ans; if (dfs (u+1,depth)) return true; } } return false; } int main () { while (cin>>n&&n) { int depth=1; a[0]=1; while (!dfs (1,depth)) depth++; for (int i=0;i<depth;i++) cout<<a[i]<<" "; cout<<endl; } return 0; }