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 }

你可能感兴趣的:(poj)