uva 215 hdu 1455 uvalive5522 poj 1011 sticks

//这题又折腾了两天 心好累

//poj、hdu数据极弱,找虐请上uvalive

题意:给出n个数,将其分为任意份,每份里的数字和为同一个值。求每份里数字和可能的最小值。

解法:dfs+剪枝

1.按降序排序,长的木棍应该优先被使用

2.一个木棍一旦确定就不应当改变,因为新得到的木棍不会更优

3.如果当前循环扫到的第一根木棍加不进去直接return false 因为可以在后面的循环里被搜到

4.如果前一根等长的没有被使用那么不进入循环

5.份数要能整除总长度才会检查是否为合法解

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<queue>
 8 #include<vector>
 9 #include<map>
10 #include<stack>
11 #include<string>
12 
13 using namespace std;
14 
15 int n;
16 int crab[64];
17 bool e[64];
18 int MAX,tot_len,want_len;
19 
20 bool cmp(int a,int b){
21     return a>b;
22 }
23 
24 bool dfs(int now,int p,int l){
25     if (now*want_len==tot_len) return true;
26     for (int i=p;i<n;i++){
27             if (e[i] && !(i>0 && e[i-1] && crab[i-1]==crab[i])){//剪枝4
28                     if (l-crab[i]==0){
29                             e[i]=false;
30                             if (dfs(now+1,0,want_len)) return true;
31                             e[i]=true;
32                             return false;//剪枝2
33                     }
34                     if (l-crab[i]>0){
35                             e[i]=false;
36                             if (dfs(now,i+1,l-crab[i])) return true;
37                             e[i]=true;
38                     }
39                     if (l==want_len) return false;//剪枝3
40             }
41     }
42     return false;
43 }
44 
45 int main(){
46     while (1){
47             scanf("%d",&n);
48             if (n==0) return 0;
49             MAX=0;
50             tot_len=0;
51             for (int i=0;i<n;i++){
52                     scanf("%d",&crab[i]);
53                     e[i]=1;
54                     tot_len+=crab[i];
55                     MAX=max(MAX,crab[i]);
56             }
57             sort(crab,crab+n,cmp);//剪枝1
58             for (want_len=MAX;want_len<=tot_len;want_len++){
59                     if ((tot_len%want_len==0) && dfs(0,0,want_len)){//剪枝5
60                             printf("%d\n",want_len);
61                             break;
62                     }
63             }
64     }
65     return 0;
66 }
67 /*
68 4
69 4 3 2 1
70 
71 9
72 5 2 1 5 2 1 5 2 1
73 4
74 1 2 3 4
75 0
76 */

 

posted @ 2015-04-29 21:15  鼠宝宝  阅读(199)  评论(0编辑  收藏  举报