其他分享
首页 > 其他分享> > AcWing - 加成序列

AcWing - 加成序列

作者:互联网

原题: AcWing 170. 加成序列 - AcWing

题意:满足如下条件的序列 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 最小的“加成序列”。

如果有多个满足要求的答案,只需要找出任意一个可行解。

分析:因为答案可以在较浅的层数找到,但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