Sticks (剪枝)

来源:互联网 发布:js判断一个月有多少天 编辑:程序博客网 时间:2024/06/05 19:35
George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.
Output
The output should contains the smallest possible length of original sticks, one per line.
Sample Input
95 2 1 5 2 1 5 2 141 2 3 40
Sample Output
6

5

问题分析:深搜+剪枝剪枝剪枝!!!已在代码中标注

第一种自己写的:

#include<stdio.h>#include<iostream>#include<algorithm>#include<string.h>using namespace std;int vis[70];int stick[70];int len,flag,sum,n,s,pre;int cmp(int a,int b){return a>b;}void dfs(int length,int num){if (num==0){flag = 1;return ;}for(int i=0; i<n; i++){if (vis[i]==0){if (length+stick[i]<=len){length += stick[i];vis[i] = 1;if (length==len)dfs(0,num-1);elsedfs(length,num-1);if (flag)return ;length -= stick[i];vis[i] = 0; if (length==0)return ;if (stick[i]==stick[i+1]){while(stick[i]==stick[i+1] && i+1<n)i++;}}}}}int main(){while(~scanf("%d", &n)){if (n==0)return 0;s = 0;for(int i=0; i<n; i++){scanf("%d",&stick[i]);s += stick[i];}sort(stick,stick+n,cmp);memset(vis,0,sizeof(vis));flag = 0;for(len = stick[0]; len<=s; len++){if (s%len)continue;dfs(0,n);if (flag)break;}printf("%d\n",len); }return 0;}


第二种写法:这里是参考网上的,没想懂在sum=0是为啥要单独讨论,不讨论就会超时

#include<stdio.h>#include<string.h>#include<stdlib.h>#include<iostream>#include<algorithm>using namespace std;int slen[70];int total;int book[70];int len;int flag;int n;int cmp(int a,int b){return a>b;}void dfs(int t,int m,int sum)//t是用掉的小棒数量,m是接下来要摆放的小棒,sum为当前长度 {if (sum == 0){int cur = 0;while(book[cur])cur++;book[cur] = 1;dfs(t+1,cur+1,slen[cur]);book[cur] = 0;return ;}  //如果当前长度已经达到枚举长度 if (sum == len){//如果小棒数量已经用完了if (t == n) flag = 1;//小棒没有用完 elsedfs(t,0,0);return ;} for(int i=m; i<n; i++){if (book[i] == 0 && sum + slen[i] <= len){//如果这一根与上一根相同并且上一根没有选,那么这一根也不选 if (book[i-1] == 0 && slen[i] == slen[i-1])continue;book[i] = 1;dfs(t+1,i+1,sum+slen[i]);book[i] = 0;//如果该小棒不能搭配,那么之后相同长度的小棒都不行 while(slen[i] == slen[i+1])i++;if (flag)return ;}}}int main(){while(~scanf("%d",&n)){if (n == 0)return 0;total = 0;for(int i=0; i<n; i++){scanf("%d",&slen[i]);total += slen[i];}sort(slen,slen+n,cmp);for(len=slen[0]; len<=total; len++){if (total % len == 0)//一定要是因数才能平分,否则大棍长度不可能相等{memset(book,0,sizeof(book));flag = 0;dfs(0,0,0);if (flag){printf("%d\n",len);break;}}}}return 0;} 


0 0
原创粉丝点击