poj1011 Sticks[剪枝题]
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[剪枝题]的更多相关文章
- poj1011 Sticks (搜索经典好题)
poj1011 Sticks 题目连接: poj1011 Description George took sticks of the same length and cut them randomly ...
- poj1011 Sticks(dfs+剪枝)
Sticks Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 110416 Accepted: 25331 Descrip ...
- poj1011 Sticks(DFS+剪枝)
题目链接 http://poj.org/problem?id=1011 题意 输入n根棍子的长度,将这n根棍子组合成若干根长度相同的棍子,求组合后的棍子的最小长度.这题是poj2362的加强版,思路与 ...
- poj-1011 sticks(搜索题)
George took sticks of the same length and cut them randomly until all parts became at most 50 units ...
- poj1011 Sticks (dfs剪枝)
[题目描述] George took sticks of the same length and cut them randomly until all parts became at most 50 ...
- POJ1011 Sticks
Description George took sticks of the same length and cut them randomly until all parts became at mo ...
- 【蓝桥杯/算法训练】Sticks 剪枝算法
剪枝算法 大概理解是通过分析问题,发现一些判断条件,避免不必要的搜索.通常应用在DFS 和 BFS 搜索算法中:剪枝策略就是寻找过滤条件,提前减少不必要的搜索路径. 问题描述 George took ...
- CF451A Game With Sticks 水题
Codeforces Round #258 (Div. 2) Game With Sticks A. Game With Sticks time limit per test 1 second mem ...
- poj1011 搜索+剪枝
DFS+剪枝 POJ2362的强化版,重点在于剪枝 令InitLen为所求的最短原始棒长,maxlen为给定的棒子堆中最长的棒子,sumlen为这堆棒子的长度之和,那么InitLen必定在范围[max ...
随机推荐
- 时钟展频技术能有效降低EMI,深入讲解展频发生器!
原文地址:https://baijiahao.baidu.com/s?id=1608649367453023659&wfr=spider&for=pc 相关文章: 1.http://b ...
- Netty(五):Netty中如何序列化数据
JDK提供了ObjectOutputStream和ObjectInputStream,用于通过网络对POJO的基本数据类型和图进行序列化和反序列化.该API并不复杂,而且可以被应用于任何实现了java ...
- XXE攻击
1.背景 现在很多应用都存在XXE(XML External Entity attack)漏洞,就是xml外部实体攻击,比如facebook,很多XML的解析器默认是含有XXE漏洞的. 2.xml的定 ...
- golang中并发sync和channel
golang中实现并发非常简单,只需在需要并发的函数前面添加关键字"go",但是如何处理go并发机制中不同goroutine之间的同步与通信,golang 中提供了sync包和channel ...
- 浅谈WPF本质中的数据和行为
WPF缩写为Windows Presentation Foundation的缩写,本文所要谈的就是WPF本质中的数据和行为,希望通过本文能对大家了解WPF本质有所帮助. 如果自己来做一个UI框架,我们 ...
- 深入详解WPF ControlTemplate
WPF包含数据模板和控件模板,其中控件模板又包括ControlTemplate和ItemsPanelTemplate,这里讨论一下WPF ControlTemplate. 其实WPF的每一个控件都有一 ...
- iOS 跳转到Appstore的链接及二维码
1.应用内部跳转到Appstore 1.跳转到应用详情 [[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"it ...
- shell实现mysql热备份
#!/bin/bash #my.hc.sh PATH=/usr/local/sbin:/usr/bin:/bin BACKDIR = /backup/mysql ROOTPASS = ******** ...
- php总结2——php中的变量、数据类型及转换、运算符、流程控制中的分支结构
2.1 php中的变量: 定义变量:$变量名称=值: 变量名称:$开头 $之后的第一位必须是字母 $第二位之后可以是字母.数字或者是下划线.习惯上变量名称有实际含义,第二个单词后首字母大 ...
- Java中synchronized
原文地址 synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种:1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用 ...