这道题一开始我想的是在排序之后只在头和尾往中间靠近来找木块, 然后就WA, 事实证明这种方法是错误的。
然后参考了别人的博客。发现别人是直接暴搜, 但是加了很多剪枝, 所以不会超时。
我也想过这个做法,但是因为觉得肯定超时所以没有写, 我显然没有想到可以这么剪枝
#include<cstdio>
#include<cstring>
#include<functional>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
using namespace std;const int MAXN = 1123;
int a[MAXN], vis[MAXN], sum, n, start;bool dfs(int cnt, int pos, int sum, int ans)
{if(cnt == n) return true;REP(i, pos, n){if(vis[i]) continue;if(sum + a[i] < ans){vis[i] = 1;if(dfs(cnt + 1, i + 1, sum + a[i], ans)) return true;vis[i] = 0;while(a[i + 1] == a[i] && i + 1 < n) i++;}else if(sum + a[i] == ans){vis[i] = 1;if(dfs(cnt + 1, 0, 0, ans)) return true;vis[i] = 0;return false;}if(sum == 0) return false;}return false;
}int main()
{while(~scanf("%d", &n) && n){sum = 0;REP(i, 0, n) {scanf("%d", &a[i]); sum += a[i];}sort(a, a + n, greater<int>());for(int i = n; i > 0; i--)if(sum % i == 0 && sum / i >= a[0]){memset(vis, 0, sizeof(vis));if(dfs(0, 0, 0, sum / i)){printf("%d\n", sum / i);break;}}}return 0;
}