POJ1011-Sticks DFS+剪枝
2013-07-21 10:49
246 查看
题目链接:http://poj.org/problem?id=1011
题目大意是有一些等长的木棍,现将他们剪成小木棍,剪短后的小木棍最多有六十四根。题目输入数据给定剪短后的小木棍的长度,求将其恢复成原来的木棍的最短长度。
本题剪枝要求较高:
剪枝(1):由于小木棍是由原来木棍剪短后得到的,那么原来木棍的长度最短的也大于等于最长的小木棍,但不会超过所有小木棍长度之和;
剪枝(2):注意到原木棍长度是等长的,则将所有小木的长度加起来后,若不能按当前要搜索的值平均分配,那么剪掉。
剪枝(3):由于所有棒子已降序排序,在DFS时,若某根棒子不合适,则跳过其后面所有与它等长的棒子;
剪枝(4):最重要的剪枝,开始没加这个剪枝,我TL,加了这个剪枝后,POJ上16ms。对于每次重新构造原始木棍长度时,若从第一根木棍开始搜索,无法组合成功,则不需要继续往后搜索,因为当前木棍若不能和其他木棍组合成原始木棍则就需要被舍弃,但是组成所有的原始木棍不能舍弃任何一根小木棍!
题目大意是有一些等长的木棍,现将他们剪成小木棍,剪短后的小木棍最多有六十四根。题目输入数据给定剪短后的小木棍的长度,求将其恢复成原来的木棍的最短长度。
本题剪枝要求较高:
剪枝(1):由于小木棍是由原来木棍剪短后得到的,那么原来木棍的长度最短的也大于等于最长的小木棍,但不会超过所有小木棍长度之和;
剪枝(2):注意到原木棍长度是等长的,则将所有小木的长度加起来后,若不能按当前要搜索的值平均分配,那么剪掉。
qsort(a,n,sizeof(int),cmp); //将所有小木棍按从大到小的顺序排序 for (i=a[0];i<=sum;i++) //我们只需枚举 最长的小木棍长度 到 所有小木棍长度之和。 { if (sum%i==0&&dfs(0,0,0,i)) //如果所有小木棍长度之和不能按当前要搜索的值平均分配,那么剪掉不搜索。因为原木棍长度等长。 { break; } }
剪枝(3):由于所有棒子已降序排序,在DFS时,若某根棒子不合适,则跳过其后面所有与它等长的棒子;
剪枝(4):最重要的剪枝,开始没加这个剪枝,我TL,加了这个剪枝后,POJ上16ms。对于每次重新构造原始木棍长度时,若从第一根木棍开始搜索,无法组合成功,则不需要继续往后搜索,因为当前木棍若不能和其他木棍组合成原始木棍则就需要被舍弃,但是组成所有的原始木棍不能舍弃任何一根小木棍!
#include<stdio.h> #include<string.h> #include<stdlib.h> #define MAX 70 #define INF 0xfffffff int a[MAX],flag[MAX]; int n; int cmp(const void *a,const void *b) { return *(int *)b-*(int *)a; } int dfs(int tot,int s,int sum,int max) //四个参数分别为tot-已经使用的小木棍数,s-上次搜索到第几根小木棍 //sum-当前已经组合的小木棍长度,max-原始木棍的长度。 { if (tot==n) //这是阀值,即所有木棍被用完,搜索结束 { return 1; } int i,sample=-1;; for (i=s;i<n;i++) { if (flag[i]||sample==a[i]) //如果当前木棍被用过了, //或者与当前木棍等长的小木棍在此次组合成原始木棍中不能用时,当前木棍也不用检索,跳过。剪枝(3); continue; flag[i]=1; if (flag[i]&&sum+a[i]<max) { if (dfs(tot+1,i,sum+a[i],max)) { return 1; } else { sample=a[i]; //这根木棍在此次组合中不能使用,则记录,下次遇到等长跳过 } } else if (sum+a[i]==max) // 若组合成一根原始木棍 { if (dfs(tot+1,0,0,max)) //则从从第一根木棍开始搜索,并且将记录的小木棍组合的长度置零重新开始组合另一根原始木棍。 return 1; else { sample=a[i]; } } flag[i]=0; if (sum==0) //剪枝(4)若上面的木棍组合成功便会return,否则代表无法组合。 break; } return 0; } int main() { while (scanf("%d",&n)!=EOF) { if (n==0) break; int i,j,sum=0,max=-INF; for (i=0;i<n;i++) { scanf("%d",&a[i]); flag[i]=0; sum+=a[i]; } qsort(a,n,sizeof(int),cmp); for (i=a[0];i<=sum;i++) { if (sum%i==0&&dfs(0,0,0,i)) { break; } } printf("%d\n",i); } return 0; }
相关文章推荐
- 一道恶心的题目 poj1011小木棍
- poj1011
- poj1011
- [搜索]poj1011
- 【poj1011】Sticks 搜索与剪枝
- poj1011
- poj1011 - Sticks
- poj1011
- POJ1011 (DFS+剪枝)
- 搜索算法(poj1011)
- 【POJ1011 Sticks】解题报告+思路+代码
- POJ1011
- hdu 1518 Square (dfs搜索可参考poj1011)
- 【poj1011】木棒
- POJ1011 dfs剪枝 半原创
- poj1011
- [搜索] ZOJ1002、ZOJ1008、ZOJ1019、POJ1011
- poj1011
- POJ1011
- poj1011