POJ 1011 - Sticks
题意:
一把等长的木段被随机砍成 n 条小木条
已知他们各自的长度,问原来这些木段可能的最小长度是多少
分析:
1. 该长度必能被总长整除
2. 从大到小枚举,因为小长度更灵活, 可拼接可不拼接
3. 因为每一跟木条都要用到, 故若轮到其中一根原始木段选它的第一根木条时,若第一根木条若不满足,则显然第一根木条在接下来任何一根原始木段都不会满足,故无解
4. 由于所有棒子已排序,在DFS时,若某根棒子未被选,则跳过其后面所有与它等长的棒子
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 int n, sum, ans, len, Max; 7 int a[100],vis[100]; 8 bool dfs(int num,int x,int j) 9 { 10 if(x == 0) 11 { 12 num--; 13 if(num == 0) return 1; 14 int i = n; 15 while(vis[i]) i--; 16 vis[i] = 1; 17 if(dfs(num, len - a[i], i-1) ) return 1; 18 vis[i] = 0; 19 } 20 else 21 { 22 for (int i = j; i > 0; i--) 23 { 24 if (vis[i]) continue; 25 if (!vis[i+1] && a[i+1] == a[i]) continue; 26 if (x < a[i]) continue; 27 vis[i] = 1; 28 if(dfs(num, x - a[i], i-1)) return 1; 29 vis[i] = 0; 30 } 31 } 32 return 0; 33 } 34 int main() 35 { 36 while(~scanf("%d",&n) && n) 37 { 38 sum = 0, Max = 0; 39 for (int i = 1; i <= n; i++){ 40 scanf("%d", &a[i]); 41 sum += a[i]; 42 Max = max(a[i], Max); 43 } 44 sort(a+1,a+1+n); 45 ans = sum; 46 for (int i = Max; i < sum ; i++) 47 { 48 if (sum % i) continue; 49 len = i; 50 memset(vis,0,sizeof(vis)); 51 if(dfs(sum/i, len, n)) 52 { 53 ans = i; 54 break; 55 } 56 } 57 printf("%d ", ans); 58 } 59 }