Sticks(poj1011/uva307)
题目大意:
乔治有一些碎木棒,是通过将一些相等长度的原始木棒折断得到的,给出碎木棒的总数和各自的长度,求最小的可能的原始木棒的长度;(就是将一些正整数分组,每组加起来和相等,使和尽可能小)
一开始做poj 32ms过,但uva3000 ms 都超时。。。而且poj discuss里给出了一组bT数据,最后uva 0.2sac的代码也跑了3 。4秒左右。discuss里的大牛据说什么奇偶性剪枝0.01ms过,可惜搜了半天也没找到具体方法。这题就这样过好了。。(参考各种空间博客才艰难ac。不过此题实在是太经典了,搜索学习剪枝必做)
对于这道题而言,剪枝的策略一般有下面6个:
①先将木棒长度从大到小进行排序,这样便于后面的选择和操作,是后面一些剪枝算法的前提。
②在枚举原木棒长度时,枚举的范围为max与sum/2之间,如果这个区间内没有找到合适的长度,那么最后原木棒的长度只能是sum。
③枚举的原木棒的长度只能是sum的约数。
④在深搜过程中,如果当前木棒和前一个木棒的长度是一样的,但是前一个木棒没有被选上,那么这个木棒也一定不会被选上。
⑤在深搜过程中,如果当前是在拼一根新木棒的第一截,但如果把可用的最长的一根木棒用上后不能拼成功的话,那么就不用再试后面的木棒了,肯定是前面拼的过程出了问题。
⑥在深搜过程中,如果当前可用的木棒恰好能补上一根原木棒的最后一截,但用它补上之后却不能用剩下的木棒完成后续的任务,那么也不用再试后面的木棒了,肯定是前面拼的过程出了问题。
参考博客:http://www.cnblogs.com/staginner/archive/2011/09/08/2171329.html
我的AC 代码:(剪枝见注释)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n,max_len,min_len,sum,ans,num,flag;
int a[10000],v[10000];
bool cmp(const int &x,const int &y)
{
return !(x<y);
}
void search(int step,int from,int cur)//step表示当前去凑的是第几根原始棒,order表示当前用了多少根碎棒子来凑第step根
{
//printf("%d %d\n",step,cur);
if (cur==ans)
{
if (step==num)
{
flag=1;
return;
}
int k;
for (k=1;k<=n && v[k];k++);
v[k]=1;
search(step+1,1,a[k]);
v[k]=0;
return;
}
for (int i=from;i<=n;i++)
{
if (v[i])
continue;
if (cur+a[i]>ans)
continue;
if (a[i]==a[i-1] && !v[i-1])
continue;//剪枝3:上一根棒和目前这根一样并且没用过,那么用这一根去凑和用上一根去凑结果一样都不能出解
//printf("kk %d %d\n",cur,cur+a[i]);
int t=a[i]+cur;
if (t!=ans && t+min_len>ans)
continue;
v[i]=1;
search(step,i+1,t);
v[i]=0;
if (t==ans)
return;
if (flag || cur==0)//剪枝4:如果当前用了1根碎棒子来凑,枚举了第一根碎棒不能出解那么跳出
return;
}
return;
}
int main ()
{
while (scanf("%d",&n)==1)
{
if (n==0)
break;
v[0]=1;
a[0]=210000000;
max_len=-1;
min_len=21000000;
sum=0;
flag=0;
for (int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if (a[i]>max_len)
max_len=a[i];
if (a[i]<min_len)
min_len=a[i];
sum+=a[i];
}
sort(a+1,a+n+1,cmp);
for (ans=max_len;ans<=sum/2;ans++)//剪枝1:答案的下界为最长的棒,上界为长度总和
{
if (sum%ans!=0)
continue;//剪枝 2:原始棒长度是总长度的约数
for (int k=1;k<=n;k++)
v[k]=0;
num=sum/ans;
search(1,1,0);
if (flag)
{
printf("%d\n",ans);
break;
}
}
if (!flag)
printf("%d\n",sum);
}
return 0;
}
|
Sticks(poj1011/uva307)的更多相关文章
- 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 ...
- UVA-307 Sticks (DFS+剪枝)
题目大意:用n根长度未必相等的木棒匹配出最多数量的等长木棒. 题目分析:枚举所有可能的等长木棒的长度,通过DFS的方式逐根匹配,在此过程中要剪枝.先将木棒长度按从大到小排序,也就是说匹配每一根等长木棒 ...
- 2018.07.03 POJ 2653 Pick-up sticks(简单计算几何)
Pick-up sticks Time Limit: 3000MS Memory Limit: 65536K Description Stan has n sticks of various leng ...
- POJ2653:Pick-up sticks(线段相交)
题目:http://poj.org/problem?id=2653 题意:题意很简单,就是在地上按顺序撒一对木棒,看最后有多少是被压住的,输出没有被压住的木棒的序号.(有点坑的就是没说清楚木棒怎么算压 ...
- Sticks(剪枝+BFS)
Problem Description George took sticks of the same length and cut them randomly until all parts beca ...
- hdu 1455 Sticks(dfs+剪枝)
题目大意: George有许多长度相同的木棍,随机的将这些木棍砍成小木条,每个小木条的长度都是整数单位(长度区间[1, 50]).现在George又想把这些小木棒拼接成原始的状态,但是他忘记了原来他有 ...
- 2015 CCPC D- Pick The Sticks(UESTC 1218) (01背包变形)
http://acm.uestc.edu.cn/#/problem/show/1218 既然二维dp表示不了,就加一维表示是否在边界放置,放置一个,两个.有一个trick就是如果只放一根,那么多长都可 ...
随机推荐
- Win7/8下提示OpenSCManager failed 拒绝访问
在我们日常使用命令行安装一些工具的时候经常提示如下错误提示,这是上市Win7或者Win8操作系统权限的原因 工具/原料 Win7,Win8操作系统 方法/步骤 1 以Win8为例,按WIN+Q ...
- redis+tomcat+nginx session共享
http://www.cnblogs.com/zhrxidian/p/5432886.html系列课程 简洁明了 http://blog.csdn.net/grhlove123/article/det ...
- (转)HashMap分析
原文地址:http://www.cnblogs.com/ITtangtang/p/3948406.html HashMap的数据结构 HashMap的底层主要是基于数组和链表来实现的,它之所以有相当快 ...
- 在Ubuntu 14 上安装 Nginx-RTMP 流媒体服务器
一:RTMP RTMP流媒体协议是 一套 Adobe 开发的音频视频实时传输协议: 二:Nginx-rtmp nginx-rtmp 是一个基于nginx的 RTMP服务模块,开源,免费 https:/ ...
- Nodejs环境变量
PATH,就是那个意思,没有特殊含义. NODE_PATH,将node_modules作为全局模块,多个安装目录用;分开.这样node在加载模块时首先会到项目目录下的node_modules目录加载相 ...
- 关于MySQL大牛周振兴的博客
博客内容比较丰富 MySQL管理 数据恢复 linux TCP 个人生活感触 不过内容总体是笔记式的,更适合自己看,不适合初学者去follow.不过对MySQL比较熟悉的人,可以看看,作为扩展眼界的途 ...
- bootstrap--双日历插件
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- validate插件:验证密码没有空格 用户名是5-10位 至少包含数字和大小写字母中的两种字符
//校验密码是否含有空格 jQuery.validator.addMethod("notblank", function(value, element) { var pwdblan ...
- Ubuntu 修复windows启动项
打开终端输入命令sudo gedit /etc/default/grub修改GRUB_TIMEOUT="10"然后在终端中输入sudo update-grubupdate 命令会自 ...
- JAVA中线程同步的方法(7种)汇总
同步的方法: 一.同步方法 即有synchronized关键字修饰的方法. 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时, 内置锁会保护整个方法.在调用该方法前,需要获得内置锁,否则就 ...