1. 程式人生 > 實用技巧 >Acwing 170 加成序列 (迭代加深搜尋)

Acwing 170 加成序列 (迭代加深搜尋)

題面

滿足如下條件的序列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;
}