Addition Chains
题面翻译
题目描述
一个与
n
n
n 有关的整数加成序列
<
a
0
,
a
1
,
a
2
,
.
.
.
,
a
m
>
<a_0,a_1,a_2,...,a_m>
<a0,a1,a2,...,am> 满足以下四个条件:
1.
a
0
=
1
1.a_0=1
1.a0=1
2.
a
m
=
n
2.a_m=n
2.am=n
3.
a
0
<
a
1
<
a
2
<
.
.
.
<
a
m
−
1
<
a
m
3.a_0<a_1<a_2<...<a_{m-1}<a_m
3.a0<a1<a2<...<am−1<am
4.
4.
4. 对于每一个
k
(
1
≤
k
≤
m
)
k(1≤k≤m)
k(1≤k≤m) 都存在有两个整数
i
i
i 和
j
(
0
≤
i
,
j
≤
k
−
1
,
i
j(0≤i,j≤k-1,i
j(0≤i,j≤k−1,i 和
j
j
j 可以相等
)
)
) ,使得
a
k
=
a
i
+
a
j
a_k=a_i+a_j
ak=ai+aj
你的任务是:给定一个整数
n
n
n ,找出符合上述四个条件的长度最小的整数加成序列。如果有多个满足要求的答案,只需要输出任意一个解即可。
举个例子,序列
<
1
,
2
,
3
,
5
>
<1,2,3,5>
<1,2,3,5> 和
<
1
,
2
,
4
,
5
>
<1,2,4,5>
<1,2,4,5> 均为
n
=
5
n=5
n=5 时的解。
输入格式
输入包含多组数据。每组数据仅一行包含一个整数 n ( 1 ≤ n ≤ 10000 ) n(1≤n≤10000) n(1≤n≤10000) 。在最后一组数据之后是一个 0 0 0 。
输出格式
对于每组数据,输出一行所求的整数加成序列,每个整数之间以空格隔开。
题目描述
输入格式
输出格式
样例 #1
样例输入 #1
5
7
12
15
77
0
样例输出 #1
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
不会dfs请睡觉
不会叠代dfs请睡觉
大致思路
-
本题我们不知道dep是多少,甚至连dep的上限也不清楚。
-
对于枚举次数不明确的题目,我们可以使用迭代加深搜索(IDA)的思路。对这道题目而言,我们可以先从dep=2开始尝试(前提是n!=1),如果dep=2不行,再尝试dep=3,这样一步步增加dep。
cin>>n;
while(n!=0){//多组输入
memset(a,0,sizeof(a));//初始化
a[1]=1;
for(int j=maxdep;maxdep<=999999;maxdep++){
if(dfs(2)){//实际的深度达不到999999
for(int i=1;i<=maxdep;i++){
cout<<a[i]<<" ";
}
cout<<endl;
break;
}
}
cin>>n;
}
-
每一个数一定等于上一个数加上 之前的数(可以是上一个数),否则的话如果是两个上一个数之前的数相加,那么上一个数就可以得到了,不需要多存一遍
-
可行性剪枝:数列每增加一个数,这个数的大小最大是在上一个数的基础上*2,如果剩下的长度中每个数都达到最大值,但最后一个数任然小于n则返回
-
优化搜索顺序:倒序枚举,因为这样能够更快地到达n
int dfs(int dep){
if(dep>maxdep){
if(a[dep-1]==n)return 1;
else return 0;
}
for(int i=dep-1;i>=1;i--){
for(int j=dep-1;j>=i;j--){
if(a[i]+a[j]<=a[dep-1])continue;
a[dep]=a[i]+a[j];
if(dfs(dep+1))return 1;
}
}
return 0;
}
AC CODE
#include<bits/stdc++.h>
using namespace std;
int n,a[49999],maxdep=1;
int dfs(int dep){
if(dep>maxdep){
if(a[dep-1]==n)return 1;
else return 0;
}
for(int i=dep-1;i>=1;i--){
for(int j=dep-1;j>=i;j--){
if(a[i]+a[j]<=a[dep-1])continue;
a[dep]=a[i]+a[j];
if(dfs(dep+1))return 1;
}
}
return 0;
}
int main(){
cin>>n;
while(n!=0){
memset(a,0,sizeof(a));
a[1]=1;
for(int j=maxdep;maxdep<=999999;maxdep++){
if(dfs(2)){
for(int i=1;i<=maxdep;i++){
cout<<a[i]<<" ";
}
cout<<endl;
break;
}
}
cin>>n;
}
return 0;
}