2014-11-25 17:26:56
思路:这题在Uva写过,现在重写竟然还是不顺手Orz...
几个剪枝:(1)木棍从大到小排序,优先取大,这样可减少递归深度
(2)枚举结果长度时要使之整除总长
(3)在递归考虑过程中如果发现 i 和 i-1 根木棍同长但 i-1 未取,那么 i 也不取
(4)如果在从头开始构成一根目标棒时就失败,那么之后也不能成功
1 /************************************************************************* 2 > File Name: p1011.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 25 Nov 2014 12:32:31 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 27 int n,sum; 28 int v[100]; 29 int vis[100]; 30 31 bool Dfs(int pos,int now,int lsum,int tar){ 32 if(lsum == sum) 33 return true; 34 for(int i = pos; i <= n; ++i) if(!vis[i]){ 35 if(i > 1 && v[i] == v[i - 1] && !vis[i - 1]) 36 continue; 37 if(now + v[i] < tar){ 38 vis[i] = 1; 39 bool flag = Dfs(i + 1,now + v[i],lsum,tar); 40 vis[i] = 0; 41 if(flag) return true; 42 else if(now == 0) return false; 43 } 44 else if(now + v[i] == tar){ 45 vis[i] = 1; 46 bool flag = Dfs(1,0,lsum + tar,tar); 47 vis[i] = 0; 48 if(flag) return true; 49 else return false; 50 } 51 } 52 return false; 53 } 54 55 int main(){ 56 while(scanf("%d",&n) != EOF && n){ 57 int tmax = 0; 58 sum = 0; 59 memset(vis,0,sizeof(vis)); 60 for(int i = 1; i <= n; ++i){ 61 scanf("%d",&v[i]); 62 tmax = max(tmax,v[i]); 63 sum += v[i]; 64 } 65 sort(v + 1,v + n + 1,greater<int>()); 66 for(int i = tmax; i <= sum; i ++) if(sum % i == 0){ 67 if(Dfs(1,0,0,i)){ 68 printf("%d\n",i); 69 break; 70 } 71 } 72 } 73 return 0; 74 }