poj1011 Sticks

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 bool anUsed[65];
 7 int L,N,stick[65];
 8 bool cmp(int a,int b)
 9 {
10     return a>b;
11 }
12 bool DFS(int nUnusedSticks,int nLeft)
13 {
14     int i,j,k;
15     if(!(nUnusedSticks||nLeft)) return 1;//假如都为0,则拼合完成 
16     if(!nLeft) nLeft=L;//新建一个要拼合的棍 
17     for(i=0;i<N;++i)
18         if(!anUsed[i]&&stick[i]<=nLeft){//剪枝 
19             if(i>0&&!anUsed[i-1]&&stick[i]==stick[i-1]) continue;//剪枝 
20             anUsed[i]=1;
21             if(DFS(nUnusedSticks-1,nLeft-stick[i])) return 1;
22             anUsed[i]=0;//可以重新再使用 
23             if(stick[i]==nLeft||nLeft==L) return 0;//下一次的递归深入中,刚建了一个新棍,结果后面没有符合条件的棍,返回这一层时stick[i]==nLeft,而这一层也要返回 
24         }            //或者这一层刚开了一个新的棍,但剩余棍中没有符合的棍即nLeft==L,这也需要返回上层 
25     return 0;
26 }
27 int main()
28 {
29     int i,totalLength;
30     while(scanf("%d",&N),N){
31         for(totalLength=i=0;i<N;++i){
32             scanf("%d",&stick[i]);
33             totalLength+=stick[i];
34         }
35         sort(stick,stick+N,cmp);//一次剪枝 
36         for(L=stick[0];L<=(totalLength>>1);++L)
37             if(totalLength%L==0){ //二次剪枝 
38                 memset(anUsed,0,sizeof(anUsed));
39                 if(DFS(N,L)) break;
40             } 
41         if(L>(totalLength>>1)) printf("%d\n",totalLength);//三次剪纸 
42         else printf("%d\n",L);
43     }
44     return 0;    
45 }

posted on 2012-08-14 21:10  小花熊  阅读(151)  评论(0编辑  收藏  举报

导航