dfs+剪枝 POJ1011

 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 }
View Code
原文地址:https://www.cnblogs.com/wsruning/p/4747248.html