#include <iostream>
using namespace std;
short s[66];
bool v[66];
short k, n, m, t, r;
bool su;
void dfs(short x, short l)
{
if (su) return ;
if (x==0)
{
x = r;
l--;
}
if (l==0)
{
su = true;
return;
}
for (int i=n;i>=0;i--)
if (!su && v[i] && s[i]<=x)
{
v[i] = false;
dfs(x-s[i],l);
v[i] = true;
if (x==s[i]) return ; // 1
if (x==r) return ; // 2
while(s[i-1]==s[i]) i--; // 3
}
}
int main()
{
while (cin>>t,t)
{
n = -1;
m = 0;
r = 0;
while(t--)
{
scanf("%d",&k);
if (k>50) continue;
n++;
s[n] = k;
m += k;
if (k>r) r = k;
v[n] = true;
}
su = false;
sort (s,s+n+1);
while (!su)
{
while (m%r != 0) r++;
dfs(r,m/r);
if (su) break;
r++;
}
cout<<r<<endl;
}
return 0;
}
剪枝:
此三处剪枝在回溯之后,及当前的s【i】已经试过不能满足。
1、用长为s【i】已证明之后肯定无法满足,但又要搜一个s【i】来满足之前一个配对(x)。矛盾,所以放弃搜索。
2、长s【i】必组成某一段,当搜索新的一段时,已确定s【i】无法满足。cut。。。
3、s【i】不满足,和s【i】等长的也无需再试。。。