标签:
http://poj.org/problem?id=1011
题意:
给定多根木棒的长度,要求将其重新组合成若干相等长度的木棒,求组合后木棒的最小长度
解法:
dfs + 重点剪枝
自己想到的剪枝太弱了 学习整理下看到的剪枝
具体看注释
代码: 700K 0MS
#include <iostream> #include <algorithm> #include <cstring> using namespace std; #define _ ios_base::sync_with_stdio(0);cin.tie(0) #define N 64 int s[N], sn, l, n, ans; bool flag, vis[N]; bool cmp(int a, int b) { return a > b; } bool dfs(int crtn, int crt, int crtl) { //在找第几根,当前下标,当前根剩余长度 if (crtn == n) { //已完成n-1根,必然能完成最后一根 return 1; } for (int i = crt; i < sn; ++i) { if (vis[i] || (i && !vis[i - 1] && s[i] == s[i - 1]) || crtl < s[i]) { //已选过||已知前一根长度相同的选不上||比剩余长度大 continue; } vis[i] = 1; if (crtl == s[i]) { //完成当前根 if (dfs(crtn + 1, 0, ans)) { //从头开始找下一根 return 1; } vis[i] = 0; return 0; //若找不到下一根,则此测试长度无解 } else { if (dfs(crtn, i + 1, crtl - s[i])) { //接着找当前根 return 1; } vis[i] = 0; if (crtl == ans) { //从头开始找一根木棍时,若从当前未标记的最长的一根无法找到解,则此测试长度无解 return 0; } } } return 0; } int main() { _; while (cin >> sn && sn) { int totl = 0; for (int i = 0; i < sn; ++i) { cin >> s[i]; totl += s[i]; } sort(s, s + sn, cmp); //降序排序 for (ans = s[0]; ans < totl; ++ans) { //从最长木棍的长度开始增加测试长度 if (totl % ans == 0) { //测试的长度可整除总长度 memset(vis, 0, sizeof(vis)); n = totl / ans; //要组的根数 if (dfs(1, 0, ans)) { break; //成功则结束循环 } } } cout << ans << endl; } return 0; }
标签:
原文地址:http://www.cnblogs.com/rsola/p/4266056.html