题意:给出一些木棒,已知这些木棒是由原来的一些等长的木棒切割而成,问原木棒最小可能长度是多少。
分析:dfs。从小到大枚举原木棒长度,然后对于每次枚举进行深搜。深搜过程就是用输入的小木棒来填充原来的一根根木棒的过程。如果我们现将一根小木棒是放在原木棒中的第一根小木棒,那么如果还不能匹配成功,则说明该小木棒无法匹配,故该原木棒长度不行。如果一根小木棒是填充一根原木棒时用的最后一根小木棒,且后面填充其他原木棒是出现了不匹配的现象回溯到这一跟小木棒的时候,不需要再尝试将这跟小木棒换掉然后用一些更小的小木棒来填充这个小木棒的长度,因为那些更小的小木棒具有更好的灵活性,他们都不能完成后面的任务,更不用说这根长度等于他们长度和的灵活性较低的小木棒了。
View Code
#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; }