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 */

 

你可能感兴趣的:(live)