加成序列(迭代加深dfs)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了加成序列(迭代加深dfs)相关的知识,希望对你有一定的参考价值。


题目描述:

满足如下条件的序列X(序列中元素被标号为1、2、3…m)被称为“加成序列”:

1、X[1]=1

2、X[m]=n

3、X[1]<X[2]<…<X[m-1]<X[m]

4、对于每个 kk(2≤k≤m2≤k≤m)都存在两个整数 ii 和 jj (1≤i,j≤k−11≤i,j≤k−1,ii 和 jj 可相等),使得X[k]=X[i]+X[j]。

你的任务是:给定一个整数n,找出符合上述条件的长度m最小的“加成序列”。

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

输入格式

输入包含多组测试用例。

每组测试用例占据一行,包含一个整数n。

当输入为单行的0时,表示输入结束。

输出格式

对于每个测试用例,输出一个满足需求的整数序列,数字之间用空格隔开。

每个输出占一行。

数据范围

1≤n≤1001≤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

这道题目,你首先可以明确地算出,最终m的长度必然是小于10的.这就是迭代加深的精髓所在,就是我们确定答案在一个比较浅的位置.

我们可以推出在20以上的数,统统都是m>6的,而50以上的,除了64统统都是大于7的,这就是我们玄学数学优化,特别加速.

优化搜索顺序:我们要让序列中的数字迅速地逼近N,自然是要i和j从大到小枚举,且j<=i,一定要注意这一点,不然你就会TLE,而且特别卡常.

排除等效冗余:我们发现,对于不同的i和j,他们的X[i]+X[j]有一定的可能性会相同,所以避免重复搜索,我们需要进行判重.

AC代码:

/*

MMM
MMMMMMM:
~MM MMM
7M+ MM
MM
MMMMMM, MM MM ,,:+MMM:
MMM MMM MM~ MM ~MMMMMMMMMMMMMMMMMMMMMMM$
ZM$ MMM MM MMMMMMMMMN MMM MMM$
MM MM8 MM OMMMMMO MM MM~
,MM MM ,MMMMM MM MMMMMMZ ,MM MMM
MM? MMDMMMMM+ , MM MM, ~MD , MM
MM8 :MMMO IMMM, MMÁÁÁÁ MM MM MMM ,MMO MM
MMM MMMMM MMMMMMM MM M8 MM MMM MM NM
MMMMMM MM ~MM MM7 MM MM7 DM
7MMM MM ÁÁÁÁ MM MMMMMM MM? MM
MMM M MM MM MMD :MM
MMM MMM IMM NMMM IMM
NMM 7MMMMMM MMMMMMMMM
MMM
MM MMM
MM DMM? MMM:
7MM MMMMMMMMMM MMMM
MM MMM MMMN MMMMMM7
MM MM MMD MMMMM
DM~ MM MM MM
NM MM MM MM=
MM MM NM MM
NM +MM MM NM MM
OM? MMM 8MM ,MM ZMZ
MM MMMM :MMM +? MMM MM
MM MMMMMMM: MM =MM +MM
MM: MMM MMM MM
MM MMMMMMMMMMMMM? MM
MM+ ?MMMMM$ MM7
MM MM
MM MM
=MM ZMM
MMM MMMM
~MMMMM MMMMMM
MM ?MMMM 8MMMM MM
MM MMMMMMN, NMMMMM ,MM
ZMM =MMMMMMMMMMMMMM DMM
,MMMMOMM8 MM7MMMM
MMM? MMM, MMMM ,MMM +MMM MMM
MM MMMM 7MMM MM MM ?MMM 8MMM8 M
:MMM NMM~ MM MM MMM MMMM
MO MM MM MM DMI ?ND
~M,ZMNIM MM 8MM :M M$ MM
MM MM MM MOM8MMM
~ MM MM D
OM? ~MM
MMMM MM MM
M MM M= MM =MM
MM M~MMMMNMMN MN
M M,MM+M?MM MM
MNOMMM ,,NDMM MM
MMM MM
MM MM
+M$ MM
MM MM
MM MM
MMMMMMMMMMMMMMMMMMMMMMMMMMNNNNNNDDZZZZIIIIIIIZZZDNMMMMM
, :~IZ8DNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN
NM MZ MM M
NM M7 MM7M
NM M+ MMDM
DM M= MMMM
DM M MMMM ZM=
DMMMMMMMMMMMMN MMMMMMMMMMMMM=
MM MM MM MM
~MMMMMMMMMMMM8 +MMMMMMMMMMMM
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<stdlib.h>
#include<queue>
#include<map>
#include<iomanip>
#include<math.h>
const int INF = 0x3f3f3f3f;
using namespace std;
typedef long long ll;
typedef double ld;
int i,j,k,l;
int n,s;
int x[110];
int sum[110];
int dfs(int now,int deep,int last)
//当前now深度,deep最大深度,
//last为上一次的数值,我们要满足数列的单调递增性.
if (x[now]==n)//找到了
return now;
if (now>=deep)//超过深度
return 0;
for(int i=now; i>=1; i--)
for(int j=i; j>=1; j--)
if(!sum[x[i]+x[j]]&&x[i]+x[j]>=last)

x[now+1]=x[i]+x[j];
sum[x[i]+x[j]]=true;
int sm=dfs(now+1,deep,x[i]+x[j]);
if(sm)
return sm;
sum[x[i]+x[j]]=false;
x[now+1]=0;

else if(!sum[x[i]+x[j]])
break;
return 0;


int main()

while(~scanf("%d",&n)&&n)

x[1]=1;
x[2]=2;
k=n;
if (n>2)

if (n>20)
k=6;
else
k=3;
for(; k<=10; k++)

memset(sum,0,sizeof sum );
memset(x,0,sizeof x);
x[1]=1;
x[2]=2;
s=dfs(2,k,3);
if(s!=0)
break;


for(i=1; i<k; i++)
printf("%d ",x[i]);
printf("%d\\n",x[k]);

return 0;

 

以上是关于加成序列(迭代加深dfs)的主要内容,如果未能解决你的问题,请参考以下文章

[dfs] aw180. 排书(IDA*+dfs深入理解+思维+好题)

构造数列 迭代加深dfs

Acw 170.加成序列

POJ-3134-Power Calculus(迭代加深DFS)

[poj 2331] Water pipe ID A*迭代加深搜索(dfs)

迭代加深搜索(IDDFS)