题目大意:
给不超过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:;
}
}