poj1011 Sticks
Description
Input
Output
Sample Input
9 5 2 1 5 2 1 5 2 1 4 1 2 3 4 0
Sample Output
65
经典搜索题,需要非常多剪枝。
#include<iostream> #include<stdio.h> #include<stdlib.h> #include<string.h> #include<math.h> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<string> #include<algorithm> using namespace std; int a[100],vis[100],len,gen,n,ji; bool cmp(int a,int b){ return a>b; } int dfs(int t,int pos,int cha) //表示正在拼第t根,接下来从pos位置開始拼。拼完这根木棒还需多少长度 { int i,j; if(cha==0){ if(t==gen)return 1; for(i=1;i<=n;i++){ if(!vis[i]){ vis[i]=1; if(dfs(t+1,i+1,len-a[i]))return 1; //当前这根一定是剩下最长的一根,且一定要拼 vis[i]=0;break; } } } else{ for(i=pos;i<=n;i++){ if(i>1 && !vis[i-1] && a[i]==a[i-1])continue; //假设这根木棒和上一根木棒的长度同样,可是上一根没有成功。那么直接跳过这根 if(!vis[i] && a[i]<=cha){ vis[i]=1; if(dfs(t,i+1,cha-a[i]))return 1; vis[i]=0; if(a[i]==cha)break; //假设当前这根木棒的长度恰好等于所差的长度,可是搜索不成功。那么就一定不能。} } } return 0; } int main() { int m,i,j,flag,sum; while(scanf("%d",&n)!=EOF && n!=0) { sum=0;ji=0; for(i=1;i<=n;i++){ scanf("%d",&a[i]); if(a[i]&1)ji++; sum+=a[i]; } if(i==1){ printf("%d\n",sum);continue; } sort(a+1,a+1+n,cmp); //从大到小排列 flag=0;memset(vis,0,sizeof(vis)); for(len=a[1];len<=sum/2;len++){ if(sum%len==0){ //必需要整除才行 gen=sum/len; if(len&1){ //假设总长度是奇数。但个数小于总根数,那么直接下一个循环 if(ji<gen)continue; } if(~len&1){ //假设总长度是偶数,可是有奇数个奇数。那么直接下一个循环 if(ji&1)continue; } if(dfs(1,1,len)){ flag=1;printf("%d\n",len);break; } } } if(!flag)printf("%d\n",sum); } return 0; }
posted on 2017-05-28 11:07 yjbjingcha 阅读(142) 评论(0) 编辑 收藏 举报