UVA-307 Sticks (DFS+剪枝)

题目大意:用n根长度未必相等的木棒匹配出最多数量的等长木棒。

题目分析:枚举所有可能的等长木棒的长度,通过DFS的方式逐根匹配,在此过程中要剪枝。先将木棒长度按从大到小排序,也就是说匹配每一根等长木棒时总是优先挑选长的。剪枝方案如下:1. 若第i-1根木棒在当前方案的匹配中没有用到并且length[i]==length[i-1],则第i根木棒也不可能用到;2.若已匹配成功cnt根等长木棒,而第cnt+1根匹配不成功,则要剪枝;3.若在匹配第cnt+1根木棒时,最长的那根木棒stick会第一个被选择,若此时第cnt+1根等长木棒匹配失败,则第cnt+1根等长木棒无须继续匹配,返回第cnt根等长木棒的匹配即可,因为与stick在此次匹配时匹配的可选木棒范围要比以后更大,此次都匹配不成,以后更匹配不成,要重新匹配第cnt根木棒,得以产生新的最长木棒stick’,再由此尝试匹配第cnt+1根等长木棒。

 

以上三条缺一不可!!!

 

代码如下:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 int w[100],n;
 6 int vis[100];
 7 bool dfs(int cur,int g,int id,int cnt,int sum){
 8     if(g*cnt == sum)
 9         return true;
10     for(int i=id;i<n;i++){
11         if(vis[i])
12             continue;
13         if(i&& !vis[i-1] && w[i-1] == w[i])///剪枝1
14             continue;
15         if(cur + w[i] == g){
16             vis[i] = 1;
17             if(dfs(0,g,0,cnt + 1,sum))
18                 return true;
19             vis[i] = 0;
20             return false;///剪枝2
21         }
22         else if (cur + w[i] <g){
23             vis[i] = 1;
24             if(dfs(cur+w[i],g,i+1,cnt,sum))
25                 return true;
26             vis[i] = 0;
27             if(cur == 0)
28                 return false;///剪枝3
29         }
30     }
31     return false;
32 }
33 
34 bool cmp(const int &a,const int &b){
35     return a>b;//sort from up to down
36 }
37 int main(){
38     while(~scanf("%d",&n)&&n){
39         int sum = 0;
40         for(int i=0;i<n;i++){
41             scanf("%d",&w[i]);
42             sum += w[i];
43         }
44         sort(w,w+n,cmp);
45         int flag=0;
46       //  for(int i=0;i<n;i++)printf("%d ",w[i]);
47         for(int i=w[0];i<=sum/2;i++){
48             if(sum%i==0){
49                 memset(vis,0,sizeof(vis));
50                 if(dfs(0,i,0,1,sum)){
51                     flag =1;
52                     printf("%d\n",i);
53                     break;
54                 }
55             }
56         }
57         if(!flag)
58             printf("%d\n",sum);
59     }
60     return 0;
61 }

 

posted @ 2016-12-21 18:11  deepwzh  阅读(370)  评论(0编辑  收藏  举报