一本通【例题4】Addition Chains——题解
又是一道剪枝剪了半天的搜索题。。。题目传送

要充分利用题目中的约束条件:1、
;2、对于每个k(1≤k≤m)k(1≤k≤m)满足ak=ai+aj(0≤i,j≤k−1)ak=ai+aj(0≤i,j≤k−1),这里i与j可以相等。由此可以推出a1一定=2(也能减少很多操作次数了吧)
还是先找找搜索过程要面临的状态和有关维度:目标数n,答案序列的长度limit,序列中的每个数ai,当前序列中的最后一个数last。
由于如果不对序列长度加以限制,普通的深搜便会“一发不可收拾”,所以这里用迭代加深搜索。
可行性剪枝考虑:
1、由于迭代加深搜索会把之前的状态全搜索一遍,所以应当限制一下limit的下界。注意到长度为k的序列能最大造出来的数为2k-1,所以序列最短应保证那个最大造出来的数>=n,预处理就行。
考虑一下搜索顺序:因为n是由小数加小数构造出来的,求最小的构造次数。因此应从大到小搜索。
考虑防等效冗杂:让从大到小枚举的两个数中的第1个正常枚举、第2个从第1个开始枚举。
继续考虑可行性剪枝:
2、当前枚举的序列里的两个数相加应大于last,只有这样才能继续搜索。
3(效率还不够,更近一步考虑一下未来):发现一个序列最大的增长方式即为让序列中最后一个数自己加自己,设这个数为a,进行k次这样的增长后序列中最后的一个数则为a*2k,每次增长操作都会增加一个数。对于当前长度为l的序列,如果last*2limit-l仍小于n,就回溯;等于n,那limit一定是答案;大于n时才继续搜索。2的幂次方可打表或预处理出。
最优性剪枝:找到答案就停止就行。
AC代码:
#include<iostream>
#include<cstdio> using namespace std; int n,a[],bj,cankao[],mi[]; void dfs(const int &limit,int k)//要填第k个(k从1开始)
{
if(bj) return;
if(k==limit)
{
for(int i=k-;i>=;i--)
for(int j=i;j>=;j--)
{
if(a[i]+a[j]==n)
{
a[k-]=n;
bj=;
return;
}
}
}
if(a[k-]*mi[limit-k+]<=n)//可行性剪枝3
{
if(a[k-]*mi[limit-k+]==n)
{
bj=;
for(int j=k-;j<limit;j++)
a[j]=a[j-]*;
}
return;
}
for(int i=k-;i>=;i--)
{
for(int j=i;j>=;j--)//防等效冗杂
if(a[i]+a[j]>a[k-])
{
if(a[i]+a[j]>=n) continue;//可行性剪枝2
a[k-]=a[i]+a[j];
dfs(limit,k+);
if(bj) return;
}
else
{
if(j==i) return;
break;
}
}
} void work()
{
bj=;
for(int len=cankao[n];len<=n;len++)
{
dfs(len,);
if(bj)
{
for(int i=;i<len;i++)
printf("%d ",a[i]);
putchar('\n');
return;
}
}
} void init()
{
int i=,step=;
while(i<=)
{
cankao[i]=step;
i*=;
step++;
}
for(i=;i<=;i++)
if(!cankao[i])
cankao[i]=cankao[i-];//以上为可行性剪枝1
i=,step=;
mi[]=;
for(int j=;j<=;j++)//2的幂次方的预处理
{
i*=;
mi[j]=i;
}
} int main()//预处理
{
init();
a[]=;a[]=;//注意序列下标0开始
scanf("%d",&n);
while(n)
{
if(n==)//处理特殊情况
{
putchar('');
putchar('\n');
}
if(n==)
cout<<"1 2\n";
if(n>=)
work();
scanf("%d",&n);
}
return ;
}
一本通【例题4】Addition Chains——题解的更多相关文章
- ZOJ1937:Addition Chains——题解
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1937 题目大意:创造一个数列,使得它: 1.单调不递减. 2.其中一个元素 ...
- 1443:【例题4】Addition Chains
1443:[例题4]Addition Chains 题解 注释在代码里 注意优化搜索顺序以及最优化剪枝 代码 #include<iostream> #include<cstdio&g ...
- 一本通例题埃及分数—题解&&深搜的剪枝技巧总结
一.简述: 众所周知,深搜(深度优先搜索)的时间复杂度在不加任何优化的情况下是非常慢的,一般都是指数级别的时间复杂度,在题目严格的时间限制下难以通过.所以大多数搜索算法都需要优化.形象地看,搜索的优化 ...
- 「一本通 1.3 例 4」Addition Chains
Addition Chains 题面 对于一个数列 \(a_1,a_2 \dots a_{m-1},a_m\) 且 \(a_1<a_2 \dots a_{m-1}<a_m\). 数列中的一 ...
- UVA 529 Addition Chains(迭代搜索)
Addition Chains An addition chain for n is an integer sequence with the following four propertie ...
- [POJ2248] Addition Chains 迭代加深搜索
Addition Chains Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5454 Accepted: 2923 ...
- poj 2248 Addition Chains (迭代加深搜索)
[题目描述] An addition chain for n is an integer sequence with the following four properties: a0 = 1 am ...
- 一本通例题-生日蛋糕——题解<超强深搜剪枝,从无限到有限>
题目传送 显然是道深搜题.由于蛋糕上表面在最底层的半径确认后就确认了,所以搜索时的面积着重看侧面积. 找维度/搜索面临状态/对象:当前体积v,当前外表面面积s,各层的半径r[],各层的高度h[]. 可 ...
- 【题解】一本通例题 S-Nim
\(\color{purple}{Link}\) \(\text{Solution:}\) 这个题就是给\(Nim\)游戏做了一个限制. 考虑一下\(\text{SG}\)函数:给定的局面下对应的\( ...
随机推荐
- 初学node.js-nodejs中实现删除用户路由
一.users_model.js 功能:定义用户对象模型 var mongoose=require('mongoose'), Schema=mongoose.Schema; var UserSche ...
- Go语言入门篇-项目常见用法&语法
一.导入包用法: //_表示仅执行该包下的init函数(不需要整个包导入) import _ "git.xx.xx/baases/identity/cachain/version" ...
- Spring Boot 深度调优,6得飞起~
项目调优 作为一名工程师,项目调优这事,是必须得熟练掌握的事情. 在SpringBoot项目中,调优主要通过配置文件和配置JVM的参数的方式进行. 一.修改配置文件 关于修改配置文件applicati ...
- ThinkPHP关联模型详解
在ThinkPHP中,关联模型更类似一种mysql中的外键约束,但是外键约束更加安全,缺点却是在写sql语句的时候不方便,ThinkPHP很好得解决了这个问题.但是很多人不动关联模型的意思.现在就写个 ...
- 使用JavaScript获取url中的参数值
今天需要用到从url中获取参数,在网上找了几个JavaScript方法,mark下来. 一些可以使用的去获取url中指定的部分:如http://www.mystuff.com.cn/aboutus ...
- golang 状态机
package main import ( "errors" "fmt" "reflect" ) type State interface ...
- Neo4j源代码分析
1.下载neo4j源码 https://github.com/neo4j/neo4j/ 参考文章 原文地址:https://blog.csdn.net/e15273/article/details/7 ...
- Paper Reading_Distributed System
最近(以及预感接下来的一年)会读很多很多的paper......不如开个帖子记录一下读paper心得 Mark一个上海交通大学东岳网络工作室的paper notebook Mark一个大神的笔记 Ed ...
- SQL Server to MySQL
使用 Navicat 导入向导迁移 会遇到以下问题 SQL Server 中的 GUID 类型字段会变成 {guid} 多个外层花括号, 导致程序问题. 部分字段类型长度不大一致, 需要手工调整. . ...
- 几个有关FPGA的概念
<数字设计——原理和实践>(John F.Wakerly)的书 FPGA同步时钟设计 简单说就是 一个系统中(或系统中的一部分)都采用同一个时钟触发.系统中的(D)触发器全部都连接到一个时 ...