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。


  1. luogu版本
    1 #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<queue>
  7. #define dbg(x) cerr<<#x<<" = "<<x<<endl
  8. #define dddbg(x,y,z) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<" "<<#z<<" = "<<z<<endl
  9. using namespace std;
  10. typedef long long ll;
  11. typedef pair<int,int> pii;
  12. template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
  13. template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
  14. template<typename T>inline T _min(T A,T B){return A<B?A:B;}
  15. template<typename T>inline T _max(T A,T B){return A>B?A:B;}
  16. template<typename T>inline T read(T&x){
  17. x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
  18. while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
  19. }
  20. inline char cmp(int a,int b){return a>b;}
  21. const int N=;
  22. int a[N],vis[N],suf[N],n,lmax,lsum,len;
  23. int dfs(int rest,int pre,int sum){//dddbg(rest,pre,len);
  24. if(!rest){
  25. if(!sum||sum==len)return ;//后面那个稍微节省少许时间
  26. else{
  27. rest=len;int flag=;
  28. for(register int i=;i<=n;++i)if(!vis[i]){pre=i;break;}
  29. vis[pre]=,flag=dfs(rest-a[pre],pre,sum-a[pre]),vis[pre]=;//★较强剪枝
  30. return flag;
  31. }
  32. }
  33. int flag=;
  34. for(register int i=pre+;i<=n;++i)//★强剪枝
  35. if(flag)break;
  36. else if(!vis[i]&&a[i]<=rest){
  37. vis[i]=,flag|=dfs(rest-a[i],i,sum-a[i]),vis[i]=;
  38. if(!flag){
  39. if(rest==a[i])return ;//★强剪枝
  40. while(a[i]==a[i+])++i;//★强剪枝
  41. }
  42. }//二分不写了
  43. return flag;
  44. }
  45.  
  46. int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
  47. read(n);int tmp=,x;
  48. for(register int i=;i<=n;++i)read(x),x<=?(lsum+=x,MAX(lmax,a[++tmp]=x)):;
  49. n=tmp;sort(a+,a+n+,cmp);//★强剪枝
  50. for(len=lmax;len<=(lsum)>>;++len)//没用的剪枝
  51. if(lsum%len==&&dfs(,,lsum))break;
  52. printf("%d\n",len>(lsum>>)?lsum:len);
  53. return ;
  54. }
  1. poj版本
    1 #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<algorithm>
  6. #include<queue>
  7. #define dbg(x) cerr<<#x<<" = "<<x<<endl
  8. #define dddbg(x,y,z) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<" "<<#z<<" = "<<z<<endl
  9. using namespace std;
  10. typedef long long ll;
  11. typedef pair<int,int> pii;
  12. template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
  13. template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
  14. template<typename T>inline T _min(T A,T B){return A<B?A:B;}
  15. template<typename T>inline T _max(T A,T B){return A>B?A:B;}
  16. template<typename T>inline T read(T&x){
  17. x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
  18. while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
  19. }
  20. inline char cmp(int a,int b){return a>b;}
  21. const int N=;
  22. int a[N],vis[N],suf[N],n,lmax,lsum,len,tot;
  23. int dfs(int rest,int pre,int sum){//dddbg(rest,pre,len);
  24. if(!rest){
  25. if(!sum||sum==len)return ;//后面那个稍微节省少许时间
  26. else{
  27. rest=len;int flag=;
  28. for(register int i=;i<=n;++i)if(!vis[i]){pre=i;break;}
  29. vis[pre]=,flag=dfs(rest-a[pre],pre,sum-a[pre]),vis[pre]=;//★较强剪枝
  30. return flag;
  31. }
  32. }
  33. int flag=;
  34. for(register int i=pre+;i<=n;++i)//★强剪枝
  35. if(flag)break;
  36. else if(!vis[i]&&a[i]<=rest){
  37. vis[i]=,flag|=dfs(rest-a[i],i,sum-a[i]),vis[i]=;
  38. if(!flag){
  39. if(rest==a[i])return ;//★强剪枝
  40. while(a[i]==a[i+])++i;//★强剪枝
  41. }
  42. }//二分不写了
  43. return flag;
  44. }
  45.  
  46. int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
  47. while(read(n)){
  48. lmax=lsum=;
  49. for(register int i=;i<=n;++i)MAX(lmax,read(a[i])),lsum+=a[i];
  50. sort(a+,a+n+,cmp);tot=;//★强剪枝
  51. for(len=lmax;len<=(lsum)>>;++len,tot=)//没用的剪枝
  52. if(lsum%len==&&dfs(,,lsum))break;
  53. printf("%d\n",len>(lsum>>)?lsum:len);
  54. }
  55. return ;
  56. }

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. 设计模式之Visitor模式(笔记)

    訪问者模式:表示一个作用于某个对象结构中的各元素操作.它使你能够不改变各元素的类的前提下定义作用于这些元素的新操作. 首先定义一个visitor抽象类,为每一个详细类声明一个visit操作 publi ...

  2. Flume-1-7-0用户手册

    介绍 概述 Apache Flume是为有效收集聚合和移动大量来自不同源到中心数据存储而设计的可分布,可靠的,可用的系统. Apache Flume的用途不仅限于日志数据聚合.由于数据源是可定制的,F ...

  3. 网络虚拟化基础协议之Geneve

    网络虚拟化最基础的技术莫过于分层(Overlay.Underlay),要实现分层有两种手段.一个是映射(Mapping),一个是封装(Encapsulation). 映射,主要思路是转发时替换报文语义 ...

  4. rtems 4.11 RTC驱动 (arm, beagle)

    RTC驱动的框架在 c/src/lib/libbsp/shared/tod.c 中,大部分功能都已经实现了,入口函数是 rtc_initialize(),BSP要实现的东西非常少. beagle的实现 ...

  5. Mysql 5.7.18 加密连接mysql_ssl_rsa_setup

    MySQL 5.7.18 下载地址: https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.18-linux-glibc2.5-x86_64. ...

  6. JBossWeb/Tomcat 初始化连接器和处理 Http 请求过程

    概述 JBossWeb 是JBoss 中的 Web 容器.他是对 Tomcat 的封装,本文以 Http 连接器为例.简单说明 JBossWeb/Tomcat 初始化连接器和处理 Http 请求过程 ...

  7. tomcat端口问题

    https://segmentfault.com/q/1010000008858162?_ea=1777730

  8. EasyPlayer windows RTSP播放器OCX插件使用说明

    鉴于大家对于EasyPlayer插件的使用还不太熟悉,特此写一篇插件的使用文档,供大家参考:EasyPlayer插件有两种,一种是基于IE的ActiveX控件,一种是基于FireFox(也支持多浏览器 ...

  9. EasyDSS RTMP流媒体解决方案之直播录像自动清理方案

    本文转自Marvin的博客: http://blog.csdn.net/marvin1311/article/details/78660592 EasyDSS_Solution直播录像清理 直播录像, ...

  10. log4j方法的使用

    log4j.properties配置 log4j.logger.webAplLogger=info, logFile log4j.appender.logFile=org.apache.log4j.F ...