此题不难,主要思路便是IDDFS(迭代加深搜索),关键在于优化。

一个IDDFS的简单介绍,没有了解的同学可以看看:

https://www.cnblogs.com/MisakaMKT/articles/10767945.html

我们可以这么想,设当前规定长度为M,题目要求得出的数为N。

在搜索中,当前的步数为step,当前的数列为 数组a。

首先来确定思路,便是在以得出的数列a中枚举每两个数相加得出sum,然后继续搜索下一步。

初步的代码便是:

void iddfs(int step) {
for(int i=1;i<=step;i++)
for(int j=1;j<=step;j++) {
a[step+1]=a[i]+a[j];
iddfs(step+1);
}
}

但是我们需要保证的数列应该是有序上升的,所以需要保证a[step+1]必须大于a[x]。

void iddfs(int step) {
for(int i=1;i<=step;i++)
for(int j=1;j<=step;j++) {
a[step+1]=a[i]+a[j];
if(a[step+1]>a[step]) continue;
iddfs(step+1);
}
}

但这样还不够,为了满足样例的需求,应该要从大到小来枚举加数。为了避免重复搜,还可以让j=i。

void iddfs(int step) {
for(int i=step;i>=1;i--)
for(int j=i;j>=1;j--) {
a[step+1]=a[i]+a[j];
if(a[step+1]<a[step]) continue;
iddfs(step+1);
}
}

现在可以发现可以简单的过样例了,但最后一个样例的时间却非常的长。所以我们应该要思考优化了。

可以发现序列的最后一个数最大都只能是\(a_{step}*2^{M-step}\)。为什么呢,因为要使最后结果最大,选的都必须是序列中最大的两个数,也就是最后一个数。结果算出来便就是\(a_{step}*2^{M-step}\)。

那么我们的优化就很简单了,如果\(a_{step}*2^{M-step}\)是小于N的,那就根本不可能有解,就需要舍去。这便是这道题剪枝的思想。

最后的代码:

#include <iostream>
#include <cstring>
using namespace std; #define N 200 int a[200],n,len,flag; void dfs(int step) {
if(step>len) return ;
if(step==len && a[step]==n) {//找到了解,输出
for(int i=1;i<=step;i++)
printf("%d ",a[i]);
puts("");
flag=1;
return ;
}
if(a[step]>=n) return ;
for(int i=step;i>=1;i--)
for(int j=step;j>=i;j--) {
if(a[i]+a[j]>a[step] && a[i]+a[j]<=n ) {
a[step+1]=a[i]+a[j];
int sum=a[i]+a[j];
for(int k=step+2;k<=len;k++)
sum*=2;
if(sum<n) continue;
dfs(step+1);
if(flag) return ;
}
}
} int main() {
while(cin>>n) {
len=0;
if( !n ) return 0;
memset(a,0,sizeof(0));
a[1]=1;a[2]=2,a[3]=4;
int m=1;
while(m<n) {//这句加不加都无所谓,对时间复杂度影响不大
m*=2;//len完全可以从1开始
len++;
}
for(len;;len++) {
dfs(1);
if(flag) break;
}
flag=0;
}
}

include

include

using namespace std;

define N 200

int a[200],n,len,flag;

void dfs(int step) {

if(step>len) return ;

if(steplen && a[step]n) {

for(int i=1;i<=step;i++)

printf("%d ",a[i]);

puts("");

flag=1;

return ;

}

if(a[step]>=n) return ;

for(int i=step;i>=1;i--)

for(int j=step;j>=i;j--) {

if(a[i]+a[j]>a[step] && a[i]+a[j]<=n ) {

a[step+1]=a[i]+a[j];

int sum=a[i]+a[j];

for(int k=step+2;k<=len;k++)

sum*=2;

if(sum<n) continue;

dfs(step+1);

if(flag) return ;

}

}

}

int main() {

while(cin>>n) {

len=0;

if( !n ) return 0;

memset(a,0,sizeof(0));

a[1]=1;a[2]=2,a[3]=4;

int m=1;

while(m<n) {

m*=2;

len++;

}

for(len;;len++) {

dfs(1);

if(flag) break;

}

flag=0;

}

}

C++解题报告 : 迭代加深搜索之 ZOJ 1937 Addition Chains的更多相关文章

  1. 迭代加深搜索 C++解题报告 :[SCOI2005]骑士精神

    题目 此题根据题目可知是迭代加深搜索. 首先应该枚举空格的位置,让空格像一个马一样移动. 但迭代加深搜索之后时间复杂度还是非常的高,根本过不了题. 感觉也想不出什么减枝,于是便要用到了乐观估计函数(O ...

  2. UVA 529 - Addition Chains,迭代加深搜索+剪枝

    Description An addition chain for n is an integer sequence  with the following four properties: a0 = ...

  3. vijos1308 埃及分数(迭代加深搜索)

    题目链接:点击打开链接 题目描写叙述: 在古埃及.人们使用单位分数的和(形如1/a的, a是自然数)表示一切有理数.如:2/3=1/2+1/6,但不同意2/3=1/3+1/3,由于加数中有同样的.对于 ...

  4. UVA 1343 - The Rotation Game-[IDA*迭代加深搜索]

    解题思路: 这是紫书上的一道题,一开始笔者按照书上的思路采用状态空间搜索,想了很多办法优化可是仍然超时,时间消耗大的原因是主要是: 1)状态转移代价很大,一次需要向八个方向寻找: 2)哈希表更新频繁: ...

  5. UVA 11212 Editing a Book [迭代加深搜索IDA*]

    11212 Editing a Book You have n equal-length paragraphs numbered 1 to n. Now you want to arrange the ...

  6. POJ1129Channel Allocation[迭代加深搜索 四色定理]

    Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14601   Accepted: 74 ...

  7. BZOJ1085: [SCOI2005]骑士精神 [迭代加深搜索 IDA*]

    1085: [SCOI2005]骑士精神 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1800  Solved: 984[Submit][Statu ...

  8. 迭代加深搜索 POJ 1129 Channel Allocation

    POJ 1129 Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14191   Acc ...

  9. 迭代加深搜索 codevs 2541 幂运算

    codevs 2541 幂运算  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 从m开始,我们只需要6次运算就可以计算出 ...

随机推荐

  1. python安装selenium和下载浏览器驱动

    1.安装selenium     方法一:可以用在cmd中用pip命令安装. python默认自带pip工具,如果在电脑上配置了pip的环境变量,打开cmd命令窗口后可以直接输入命令pip insta ...

  2. Linux命令:popd

    语法 popd [-n] [+N | -N | dir] 把目录弹栈,就是从栈里删除.popd只有删除一种意思,不像pushd,既有压栈,又有移动栈内目录的功能. 不带任何参数,模式删除栈顶,即最上面 ...

  3. U3D 设置帧率与垂直同步

    1,设置帧率: Application.targetFrameRate = 60: //-1为无限制 2,垂直同步 project settings -> quality,任何level的垂直同 ...

  4. spring中Constructor、@Autowired、@PostConstruct的顺序

    其实从依赖注入的字面意思就可以知道,要将对象p注入到对象a,那么首先就必须得生成对象p与对象a,才能执行注入.所以,如果一个类A中有个成员变量p被@Autowired注解,那么@Autowired注入 ...

  5. 快速干掉Windows Defender

    1.快捷键Win+R,调出"运行"对话框,输入"gpedit.msc",打开组策略编辑器: 2.展开"计算机配置"→"管理模板&q ...

  6. MySQL多实例的环境下,服务器端本地连接到指定实例的问题(sock方式连接)

    涉及到sock连接的问题. 为了测试MySQL的某些个特性,在一个机器上安装了多个MySQL的实例,如下截图,有两个实例,一个端口是8000,一个端口是8001.在使用mysql -uroot -p ...

  7. C# 异步机制

    Delegate.Invoke Delegate.Invoke is used to execute a delegate on the current thread. A delegate is j ...

  8. python day07笔记总结

    2019.4.4 S21  day07笔记总结 一.深浅拷贝 1.copy.copy()     浅拷贝 deep.copy()    深拷贝 2.一般情况 1.str/int/bool 是不可变类型 ...

  9. 定位篇align_measurements

    算子:create_shape_model(Template : : NumLevels, AngleStart, AngleExtent, AngleStep, Optimization, Metr ...

  10. 导弹拦截问题(DP+贪心)

    1. 拦截导弹(Noip1999) 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度. ...