dfs+剪枝 POJ1011
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 6 using namespace std; 7 8 int n; 9 int stick[70]; 10 bool mark[70]; 11 int sum; 12 int len; 13 int num; 14 15 bool cmp(int a,int b) 16 { 17 return a>b; 18 } 19 20 bool dfs(int s,int k,int cnt) 21 { 22 if(cnt==num) 23 return true; 24 else if(s==len) 25 return dfs(0,0,cnt+1); 26 else 27 { 28 int pre=0; 29 int i; 30 for(i=k;i<n;i++) 31 { 32 if(mark[i]&&stick[i]!=pre&&stick[i]+s<=len)//剪枝,如果当前木条总长度加这根木条长度大于平均长度的话,则删去,不再向下进行 33 { 34 pre=stick[i]; 35 mark[i]=false; 36 if(dfs(stick[i]+s,i+1,cnt)) 37 break; 38 mark[i]=true; 39 if(k==0) 40 return false; 41 } 42 } 43 if(i==n) 44 return false; 45 else 46 return true; 47 } 48 } 49 50 int main() 51 { 52 while(scanf("%d",&n)!=EOF&&n) 53 { 54 sum=0; 55 for(int i=0;i<n;i++) 56 { 57 scanf("%d",&stick[i]); 58 sum+=stick[i]; 59 } 60 sort(stick,stick+n,cmp);//按从大到小排序 61 for(len=stick[0];len<sum;len++)//木条长度取值范围为最长木条,到总木条长度和 62 { 63 if(sum%len==0)//第一次剪枝,木条总长度,必须能够整除每支木条的长度 64 { 65 memset(mark,true,sizeof(mark)); 66 num=sum/len; 67 if(dfs(0,0,0)) 68 break; 69 } 70 } 71 cout<<len<<endl; 72 } 73 return 0; 74 }