题目大意:
给不超过64根棍子,将它们分成长度相等的若干组,使每组长度最小
分析:
此题是K题Square的升级版:https://blog.csdn.net/wangyucong1999310/article/details/80541217
棒子多了,组数还需要枚举。做法大体相同,需要多两个剪枝的地方:
1.棒子是从大到小排序的,所以如果某一组的第一根棒子搜索失败,就没必要再搜了。因为每根棒子都要用上,第一根棒子搜索失败,那么它在后面也一定用不上。
2.如果某一组的最后一根棒子搜索失败,也没必要再搜了。为什么呢?假设搜索失败的这根长度为m,就算后面可以有若干个小棒组合成m顶替它的位置也不行。因为若干个小棒用起来可以自由组合,即使这样都搜索失败,把它们拼成m来用自然更不可能成功
代码:
#include <iostream> #include <algorithm> #include <string.h> using namespace std; int n, num[64] = {0}; bool found, vis[64] = {0}; void dfs(int len, int now, int c, int start){ if (now == 0){//找到一组,重设参数 now = len; c--; start = 0; } if (c == 1) found = 1;//找到n-1组,跳出 if (found) return; for (int i = start, last = -1; i < n; i++){//从上一根棒子的位置开始找 if (vis[i] || num[i] > now || num[i] == last) continue; vis[i] = 1; dfs(len, now-num[i], c, i+1); if (found) return; vis[i] = 0; last = num[i]; if (now == len || now == num[i]) return;//剪枝,第一根或最后一根失败时直接返回 } } bool cmp(int a, int b){ return (a > b); } int main(){ while (cin >> n){ if (n == 0) return 0; int sum = 0; for (int i = 0; i < n; i++){ cin >> num[i]; sum += num[i]; } sort(num, num + n, cmp); for (int i = n; i > 1; i--){//枚举组数 if (sum % i == 0){ found = 0; memset(vis, 0, sizeof(vis)); dfs(sum/i, sum/i, i, 0); if (found){ cout << sum / i << endl; goto exit; } } } cout << sum << endl; exit:; } }