一本通【例题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}\)函数:给定的局面下对应的\( ...
随机推荐
- python multiprocessing模块 介绍
一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu\_count\(\)查看),在python中大部分情况需要使用多进 ...
- Keil共存的方法 - Keil MDK兼容Keil C51,实操可行
记录一下成功使Keil MDK和Keil C51共存的过程! 之前一直用Keil C51开发,最近需要用到ARM9内核的IC,就需要Keil C51和Keil MDK共存.看了一下网上几个教程,方法大 ...
- AcWing 875. 快速幂
题目链接:https://www.acwing.com/problem/content/description/877/ 快速幂模板题,计算ab mod p 的值,a,b,p大概1e9左右,可以快速计 ...
- P2562kitty猫基因
这道题是安徽NOI省选题,但是难度并没有那么难. 这道题是一个字符串的递归题,有很多大佬用线段树来写的(我也想学线段树,lowbit当头一棒).题意为全部相同则输出B或A,不同则分成长度相同的两个子串 ...
- Vim实用技巧(一)
vim 命令按键规定 标记 含义 x 按一次 x dw 按一次 d, w dap 按一次 d, a, p 同时按 和 n g<C-]> 按 g, 然后同时按 和 ] <C-=> ...
- Luogu P5470 [NOI2019]序列
题目 可以直接贪心,但是用模拟费用流推的话会更轻松. 首先有一个显然的建图方式: \(S\)到\(0\)流量为\(k\),费用为\(0\). \(0\)到\(a_i\)流量为\(1\),费用为\(-a ...
- 20170309工作笔记--------如何用好dialog,想变什么样就变成什么样
(1)首先自定义一个dialog的div,并且写内容 (2)运用相应的代码进行控制,弹出dialog $(".tel").click(function() { $("#d ...
- javascript xml转json
1.代码 //加载xml数据 function loadXml(str) { if (str == null) { return null; } var doc = str; try{ doc = c ...
- django字段类型(Field types)介绍
字段类型(Field types) AutoField 它是一个根据 ID 自增长的 IntegerField 字段.通常,你不必直接使用该字段.如果你没在别的字段上指定主 键,Django 就会自动 ...
- C#/Java 调用WSDL接口及方法
一.C#利用vs里面自带的“添加web引用”功能: 1.首先需要清楚WSDL的引用地址 如:http://www.webxml.com.cn/Webservices/WeatherWebServic ...