洛谷P1120 小木棍(sticks数据加强版)
题目描述
乔治有一些同样长的小木棍,他把这些木棍随意砍成几段,直到每段的长都不超过50。
现在,他想把小木棍拼接成原来的样子,但是却忘记了自己开始时有多少根木棍和它们的长度。
给出每段小木棍的长度,编程帮他找出原始木棍的最小可能长度。
输入输出格式
输入格式:
输入文件共有二行。
第一行为一个单独的整数N表示砍过以后的小木棍的总数,其中N≤65
(管理员注:要把超过50的长度自觉过滤掉,坑了很多人了!)
第二行为N个用空个隔开的正整数,表示N根小木棍的长度。
输出格式:
输出文件仅一行,表示要求的原始木棍的最小可能长度
输入输出样例
输入样例#1:
9
5 2 1 5 2 1 5 2 1
输出样例#1:
6
把普通版的代码改了读入直接交上去,1700+ms爬过去了……
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 int st[100],num;//个数 8 bool vis[100]; 9 int n,sum; 10 int len; 11 int cmp(const int a,const int b){return a>b;} 12 bool dfs(int s,int now,int p){ 13 //目前在组装第s根棍子,这根棍子已经组装了now长度,从所有短木棍中的第p+1个开始枚举 14 bool flag=false; 15 if(now==0)flag=1; 16 if(s==num)return true;//拼够数量了 17 for(int i=p+1;i<=n;i++){ 18 if(vis[i])continue; 19 if(now+st[i]==len){ 20 vis[i]=1; 21 if(dfs(s+1,0,0))return true;//开始拼下一根 22 vis[i]=0;//先还原 23 return false;//再返回 24 } 25 else if(now+st[i]<len){ 26 vis[i]=1; 27 if(dfs(s,now+st[i],i))return true;//尝试继续拼这一根 28 vis[i]=0; 29 if(flag)return false; 30 //开始拼一根木棍时,如果用剩下最长的木棍开始搜不能成功,用比它更短的搜也没有意义,所以跳出 31 while(st[i]==st[i+1])i++;//不再尝试相同长度的 32 } 33 } 34 return false; 35 } 36 int main(){ 37 scanf("%d",&n); 38 sum=0; 39 int i,j; 40 int tmp=n; 41 int tmps; 42 int cct=0; 43 while(tmp--){ 44 scanf("%d",&tmps); 45 if(tmps>50)continue; 46 cct++; 47 st[cct]=tmps; 48 sum+=tmps; 49 } 50 n=cct; 51 /* 52 for(i=1;i<=n;i++){ 53 scanf("%d",&st[i]); 54 55 sum+=st[i]; 56 }*/ 57 sort(st+1,st+n+1,cmp);//从大到小排序,开始枚举 58 for(i=st[1];i<=sum;i++){//枚举长度 59 if(sum%i!=0)continue;//只有能整除,才尝试按这个长度拼 60 num=sum/i;//预计拼的个数 61 len=i; 62 memset(vis,0,sizeof vis); 63 if(dfs(1,0,0)){ 64 printf("%d\n",i);//成功就输出 65 break; 66 } 67 } 68 return 0; 69 }
本文为博主原创文章,转载请注明出处。