知识点:迭代搜索,剪枝
题意:
构造一个递增的序列
\(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\)
思路
- 首先是一道搜索应该是明晰的,最优性考虑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
浙公网安备 33010602011771号