知识点:迭代搜索,剪枝

题意:

构造一个递增的序列
\(a_0,a_1,a_2,...a_n\)
满足
\(a_0=1,a_n=n,递增,对于a_k存在a_k=a_i+a_j,其中i,j小于k\)

思路

  1. 首先是一道搜索应该是明晰的,最优性考虑bfs,但是由于给定空间大小的限制,bfs会空间溢出。但是dfs求得最优解时间过长,可以考虑迭代搜索,迭代搜索像是bfs和dfs结合,给dfs设置最大搜索深度。看在限制的深度内是否能搜出解,所以从小到大枚举深度限制,如果时间还够,那么就搜深度限制更深的情况,否则结束搜索。结合了dfs和bfs的特点,适合于最优性的搜索问题,属于bfs的妥协性替代方案。
    2.剪枝:主要是可行性剪枝,\(a_i+a_j<=n\),在当前数m位以后数最大是\(a_x*2^m<=n\)

题解

#include<cstdio>
#include<iostream>
#include<cmath>
#include<vector>
#include<string>
#include<cstring>
#include<algorithm>
#define rep(i,l,n) for(int i=(l);i<=(n);++i)
#define ll long long
using namespace std;
int t,n;
int a[100],ksm2[50]={1};
void init()
{
    rep(i,1,30)ksm2[i]=ksm2[i-1]<<1;
    return ;
}
bool dfs(int ax,int x,int limit)
{
    if(x>limit+1)return false;
    if(ax==n)
    {
        return true;
    }
    for(int i=x-1;i>=1;--i)
        for(int j=x-1;j>=1;--j)
        {
            if(a[i]+a[j]<=n&&(a[i]+a[j])*ksm2[(limit-x)]>=n)
            {
                a[x]=a[i]+a[j];
                if(dfs(a[x],x+1,limit))return true;
                a[x]=0;
            }
        }
    return false;
}
int main()
{
    init();
    while(scanf("%d",&n))
    {
        if(n==0)
        {
            break;
        }
        else if(n==1)
        {
            printf("1\n");
            continue;
        }
        a[1]=1;
        rep(i,2,n)
        {
            if(dfs(1,2,i))
            {
                rep(j,1,i-1)printf("%d ",a[j]);
                printf("%d\n",a[i]);
                break;
            }
        }
    }
//    system("pause");
    return 0;
}
 posted on 2022-09-18 20:47  8号选手  阅读(18)  评论(0)    收藏  举报