https://vjudge.net/problem/POJ-1011

此题很重要。


很欢(e)乐(xin)的一道搜索剪枝题。。poj数据还是太水了,我后来想不出来剪枝方法了,就加了句掐了时间语句交上去骗了一个AC。。洛谷上加强数据掉了4个点。


题意(翻译)  ,要确定一个长度让所有短木棍拼的出来。由于数据看起来很小N只有64,所以要搜索。但是怎么搜还是关键。由于枚举长度不满足答案单调性,所以不好二分,只能从小到大枚举,找到就输出。每次check的dfs就是看可不可以选出恰好拼出一根长度len的,可以则继续拼下一根,直到恰好拼完就返回1。

下面讲剪枝即其他常数优化,没想到的加了下划线,是翻题解的。

剪枝一:枚举长度从最长木棍长度开始,这个不用说了吧。。然后一个几乎没用的优化,枚举长度到maxlen/2还不行就只能输出maxlen了。

剪枝二:避免完全无效的搜索,每次枚举的长棍如果不能整除累计总长的话,肯定拼不上来的呢。

剪枝三:木棍len要从大到小去拼。这个没法证,就是一种感觉(生活经验):先定下大的,再用碎的去凑上可能会更高效。强剪枝。

剪枝四:要考虑什么情况会造成搜索的时候重复搜索。分析可知,我现在选了这一根棒拼上去,下一根就按顺序找后面的就行了,否则我可能下次选了后面那根,再选前面的这根,就属于重复的。即为代码中的pre。

剪枝五:考虑拼完一根木棒后,不要再像code中的line34那样去找没用过的填上去。试想,我在剩下的里面拼不了了。我已经知道现在肯定不行,就果断返回。否则还会再搜当下其他棒。具体对应line26开始的,也就是我随便找一个开始填,能就能,不能就不能,反正他迟早被用。中强剪枝。

剪枝六:(pj组都会的常识)用flag标记以提前退出。

剪枝七最有效的剪枝之一,比较难想,可能我太菜了。继剪枝五,如果我现在这根填完恰好拼凑成了一根长棍,下次开始重新拼不行的话,那放弃之后的枚举,直接返回失败。用反证法瞎想一下:已知当前用的长棒恰填好一长棍,剩下的拼不了了,假设我存在一种用之后的更短木棍拼好当前长棍,剩下的能拼完的方案,那我完全可以把短的木棒看成拼出之前那一根木棒的效果,我完全可以交换一下两者位置,则同样可行,与已知矛盾,得证。举个例子,8 5 3 1 2,假若5恰好拼出来了,后面不行。我可以换用3和2达到同样效果,但用反证法发现也不行。最强剪枝

剪枝八:长度相同的木棒,当我用其中一个填入时不行,另外的就不试了。很好想,实测效果也很好。强剪枝。

剪枝九:这个没写,觉得没必要,就是二分找第一个比rest小的木棒。

这题剪枝很多,而且在luogu强数据下,少一个基本都要TLE。希望记住这些思路。

坑死我了,写了几个小时。

WA记录:?不存在,只有TLE。


 luogu版本
1 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define dddbg(x,y,z) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<" "<<#z<<" = "<<z<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
inline char cmp(int a,int b){return a>b;}
const int N=;
int a[N],vis[N],suf[N],n,lmax,lsum,len;
int dfs(int rest,int pre,int sum){//dddbg(rest,pre,len);
if(!rest){
if(!sum||sum==len)return ;//后面那个稍微节省少许时间
else{
rest=len;int flag=;
for(register int i=;i<=n;++i)if(!vis[i]){pre=i;break;}
vis[pre]=,flag=dfs(rest-a[pre],pre,sum-a[pre]),vis[pre]=;//★较强剪枝
return flag;
}
}
int flag=;
for(register int i=pre+;i<=n;++i)//★强剪枝
if(flag)break;
else if(!vis[i]&&a[i]<=rest){
vis[i]=,flag|=dfs(rest-a[i],i,sum-a[i]),vis[i]=;
if(!flag){
if(rest==a[i])return ;//★强剪枝
while(a[i]==a[i+])++i;//★强剪枝
}
}//二分不写了
return flag;
} int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
read(n);int tmp=,x;
for(register int i=;i<=n;++i)read(x),x<=?(lsum+=x,MAX(lmax,a[++tmp]=x)):;
n=tmp;sort(a+,a+n+,cmp);//★强剪枝
for(len=lmax;len<=(lsum)>>;++len)//没用的剪枝
if(lsum%len==&&dfs(,,lsum))break;
printf("%d\n",len>(lsum>>)?lsum:len);
return ;
}
 poj版本
1 #include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define dddbg(x,y,z) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<" "<<#z<<" = "<<z<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
inline char cmp(int a,int b){return a>b;}
const int N=;
int a[N],vis[N],suf[N],n,lmax,lsum,len,tot;
int dfs(int rest,int pre,int sum){//dddbg(rest,pre,len);
if(!rest){
if(!sum||sum==len)return ;//后面那个稍微节省少许时间
else{
rest=len;int flag=;
for(register int i=;i<=n;++i)if(!vis[i]){pre=i;break;}
vis[pre]=,flag=dfs(rest-a[pre],pre,sum-a[pre]),vis[pre]=;//★较强剪枝
return flag;
}
}
int flag=;
for(register int i=pre+;i<=n;++i)//★强剪枝
if(flag)break;
else if(!vis[i]&&a[i]<=rest){
vis[i]=,flag|=dfs(rest-a[i],i,sum-a[i]),vis[i]=;
if(!flag){
if(rest==a[i])return ;//★强剪枝
while(a[i]==a[i+])++i;//★强剪枝
}
}//二分不写了
return flag;
} int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
while(read(n)){
lmax=lsum=;
for(register int i=;i<=n;++i)MAX(lmax,read(a[i])),lsum+=a[i];
sort(a+,a+n+,cmp);tot=;//★强剪枝
for(len=lmax;len<=(lsum)>>;++len,tot=)//没用的剪枝
if(lsum%len==&&dfs(,,lsum))break;
printf("%d\n",len>(lsum>>)?lsum:len);
}
return ;
}

poj1011 Sticks[剪枝题]的更多相关文章

  1. poj1011 Sticks (搜索经典好题)

    poj1011 Sticks 题目连接: poj1011 Description George took sticks of the same length and cut them randomly ...

  2. poj1011 Sticks(dfs+剪枝)

    Sticks Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 110416   Accepted: 25331 Descrip ...

  3. poj1011 Sticks(DFS+剪枝)

    题目链接 http://poj.org/problem?id=1011 题意 输入n根棍子的长度,将这n根棍子组合成若干根长度相同的棍子,求组合后的棍子的最小长度.这题是poj2362的加强版,思路与 ...

  4. poj-1011 sticks(搜索题)

    George took sticks of the same length and cut them randomly until all parts became at most 50 units ...

  5. poj1011 Sticks (dfs剪枝)

    [题目描述] George took sticks of the same length and cut them randomly until all parts became at most 50 ...

  6. POJ1011 Sticks

    Description George took sticks of the same length and cut them randomly until all parts became at mo ...

  7. 【蓝桥杯/算法训练】Sticks 剪枝算法

    剪枝算法 大概理解是通过分析问题,发现一些判断条件,避免不必要的搜索.通常应用在DFS 和 BFS 搜索算法中:剪枝策略就是寻找过滤条件,提前减少不必要的搜索路径. 问题描述 George took ...

  8. CF451A Game With Sticks 水题

    Codeforces Round #258 (Div. 2) Game With Sticks A. Game With Sticks time limit per test 1 second mem ...

  9. poj1011 搜索+剪枝

    DFS+剪枝 POJ2362的强化版,重点在于剪枝 令InitLen为所求的最短原始棒长,maxlen为给定的棒子堆中最长的棒子,sumlen为这堆棒子的长度之和,那么InitLen必定在范围[max ...

随机推荐

  1. BCG菜单button的简单使用

    一,新建一个BCGprojectCBCGPMenuButton,基于对话框. 二.添加一个button,并关联一个CButton类型的变量m_btn1.然后手动将类型改CBCGPMenuButton成 ...

  2. Centos6.0使用第三方YUM源(EPEL,RPMForge,RPMFusion)

    yum是centos下很方便的rpm包管理工具,配置第三方软件库使你的软件库更加丰富.以下简单的讲下配置的步骤. 首先,需要安装yum-priorities插件: yum install yum-pr ...

  3. Spring学习八----------Bean的配置之Resources

    © 版权声明:本文为博主原创文章,转载请注明出处 Resources 针对于资源文件的统一接口 -UrlResource:URL对应的资源,根据一个URL地址即可创建 -ClassPathResour ...

  4. UML类图简明教程

    作者:郭孝星 微博:郭孝星的新浪微博 邮箱:allenwells@163.com 博客:http://blog.csdn.net/allenwells Github:https://github.co ...

  5. android开发系列之视频断点续传

    今天在这篇博客里面,我想说说自己在这几天遇到的一个棘手的问题,就是视频断点续传的问题.其实这在我们开发中是一个很常见的应用场景,比如视频.音频.pdf等相关的文档.如果之前没有接触过的话,你也许会被这 ...

  6. GenericServlet 、Servlet和httpServler他们之间的关系

    1.GenericServlet类是所有Servlet类的祖先类. 2.HttpServlet类继承了GenericServlet类. 3.Servlet有两个非常重要的的对象,可以说是java we ...

  7. sqlserver中的时间比较

    例子: select count(*) from table where DATEDIFF ([second], '2004-09-18 00:00:18', '2004-09-18 00:00:19 ...

  8. TP 框架 如果去掉表前缀

    #jd_admin_abc 去掉前缀 C('DB_PREFIX')=获取前缀 结果为admin_abc $table_Name=str_replace(C('DB_PREFIX'), '', $tab ...

  9. 【ASP.NET】巧用Cookie实战

    上篇介绍了究竟什么是Cookie.究竟是干什么用的,这篇博客具体具体的说一下.Cookie究竟怎样用. 首先建立如图所看到的的界面.通过该界面可登录到某个站点.详细要求例如以下: ·在首次登录后,将登 ...

  10. 异常: 2 字节的 UTF-8 序列的字节 2 无效。

    具体异常: 十二月 08, 2015 7:16:55 下午 org.apache.catalina.core.StandardWrapperValve invoke 严重: Servlet.servi ...