#include <stdio.h> #include <stdlib.h> #include <string.h> #define DEBUG #ifdef DEBUG #define debug(...) printf( __VA_ARGS__) #else #define debug(...) #endif int n, len, count; char found; int stick[64]; int st[64]; /* st[k] = sum{a[k]...a[n-1]}, 某根木棒和所有比它短的木棒加起来的长度 */ char used[64]; static int compare(const void *p1, const void *p2) { return *((int *)p2) - *((int *)p1); } /* 第k个小木棒开始搜索, sum:木棒还原好的长度, num: 已还原好的木棒数 */ void dfs(int k, int sum, int num) { int i, pre; if (num == count) { found = 1; return; } if (sum == len) { dfs(0, 0, num+1); } else { //从第k跟木棒开始搜索,如果有一根木棒满足: //1 未被使用 //2 之前没有相同长度的木棒出现过 //3 它的长度加上已拼凑好的长度不会超过原始长度 //4 sum加上它自己和所有比它短的木棒的长度必须超过原始长度 //则把这根木棒拼凑过去 for (pre = -1, i = k; i < n; i++) { if (!used[i] && stick[i] != pre && sum+stick[i] <= len && sum+st[i] >= len) { pre = stick[i]; debug("选择%d加在第%d根木棒\n", stick[i], num+1); used[i] = 1; dfs(i+1, sum+stick[i], num); if (found) return; debug("否定%d\n", stick[i]); used[i] = 0; if (k == 0) break; /* 原始木棒的第1根木棒总是用长度最大的, 不用往后找 */ } } } } int main() { int i, j, k, sum; while (scanf("%d", &n), n != 0) { sum = 0; found = 0; for (i = 0; i < n; i++) { scanf("%d", stick+i); sum += stick[i]; } qsort(stick, n, sizeof(int), compare); st[n-1] = stick[n-1]; for (i = n-2; i >= 0; i--) { st[i] = st[i+1]+stick[i]; } for (i = stick[0]; i <= sum; i++) { if (sum % i == 0) { debug("----------长度为%d的搜索过程------------\n", i); len = i; count = sum/i; memset(used, 0, sizeof(used)); dfs(0, 0, 0); debug("还原结果为: "); for (k = 0; k < n; k++) { debug("%d ", used[k]); } debug("\n\n"); if (found) { break; } } } printf("%d\n", found? len : sum); } return 0; }