poj1011
题意:一些木棍,已知每个的长度,把他们全用上,去拼成一些长度相等的木棍,最小长度是多少。
分析:dfs。先计算所有木棒的长度之和,然后枚举每个能被整除这个和的长度作为结果,并递归判断是否可行。
递归过程需要加一些优化:
1.先把木棍从大到小排序,大木棍的灵活性低,较难满足,因此先判断。
2.在拼一个木棍时所使用的第一个小木棍如果不行,那么当前大木棍的长度可以被舍弃。
#include <iostream> #include <algorithm> using namespace std; const int maxn = 64; int t, n, stick[maxn], each, ok, total, num; bool used[maxn]; void init() { int i; total = 0; for (i = 0; i < n; i++) { scanf("%d", &stick[i]); total += stick[i]; } ok = false; memset(used, 0, sizeof(used)); } void dfs(int length, int start) { int i; if (ok) return; if (length >= total) { ok = true; return; } if (length % each == 0) { i = start; while (used[i]) i++; used[i] = true; dfs(length + stick[i], i + 1); used[i] = false; return; } for (i = start; i < n; i++) { if (used[i]) continue; if (stick[i] + length < length / each * each + each) { used[i] = true; dfs(length + stick[i], i + 1); used[i] = false; if (ok) return; }else if (stick[i] + length == length / each * each + each) { used[i] = true; dfs(length + stick[i], 0); used[i] = false; return; } } } int main() { int i, t, ans; //freopen("t.txt", "r", stdin); while (cin >> n && n != 0) { init(); sort(stick, stick + n); for (i = 0; i < n / 2; i++) { t = stick[i]; stick[i] = stick[n - i - 1]; stick[n - i - 1] = t; } for (i = stick[0]; i < total; i++) if (total % i ==0) { each = i; num = total / i; dfs(0, 0); if (ok) { ans = each; break; } } if (!ok) ans = total; cout << ans << endl; } return 0; }