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 }