AcWing - 加成序列
作者:互联网
题意:满足如下条件的序列 X(序列中元素被标号为 1、2、3…m)被称为“加成序列”:
-
X[1]=1
-
X[m]=n
-
X[1]<X[2]<…<X[m−1]<X[m]
-
对于每个 k(2≤k≤m)都存在两个整数 i 和 j (1≤i,j≤k−1. i 和 j 可相等),使得 X[k]=X[i]+X[j]。
你的任务是:给定一个整数 n,找出符合上述条件的长度 m 最小的“加成序列”。
如果有多个满足要求的答案,只需要找出任意一个可行解。
分析:因为答案可以在较浅的层数找到,但dfs是深搜后回溯,所以会浪费很多时间,可以用迭代加深。
碎碎念:看题解视频中有一行是清空vis数组的步骤,一直没明白为什么在这个位置,而且没有的话还过不了。然后就按照dfs的常规思路想了想觉得可以加一个回溯,然后在每次拓展深度限制那里加一个清空数组的操作,结果就过了,说明这两步应该在某种程度上是等价的。
题解:
#include <bits/stdc++.h> using namespace std; const int N=105; bool vis[N]; int path[N]; int n; bool dfs(int now,int dep) { //退出条件 if(now==dep) { return path[now-1]==n;//判断是否满足结尾答案,如果满足返回true,否则返回false } //memset(vis,0,sizeof vis);就是这里! //遍历枚举 for(int i=now-1;i>=0;i--)//剪枝:优化搜索顺序 { for(int j=i;j>=0;j--) { int s=path[i]+path[j]; if(s<=n&&s>path[now-1]&&!vis[s])//判断是否满足条件:单调递增,未遍历过 { vis[s]=true; path[now]=s; if(dfs(now+1,dep)) return true;//继续深入 vis[s]=false;//回溯 path[now]=0; } } } return false; } int main() { path[0]=1; while(cin>>n&&n) { //迭代加深:用dep记录深度限制,如果找不到答案就dep+1 int dep=1; while(!dfs(1,dep)) { memset(vis,0,sizeof vis); dep++; } for(int i=0;i<dep;i++) { cout<<path[i]<<" "; } cout<<endl; } return 0; }
以上代码参考yxc老师的部分代码,yxcyyds!
(仅代表个人思考。如有错误,欢迎礼貌指正。如有疑问,欢迎友好交流。鄙人愚笨,敬请原谅。)
标签:dep,int,dfs,vis,加成,序列,path,now,AcWing 来源: https://www.cnblogs.com/atomsh/p/15027349.html