题目传送门

//爆搜加剪枝的过程,自己剪枝太弱了,恶补中

//经典搜索加剪枝

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define ll long long
const int maxn = 70;
int L,sum,n;//L表示枚举的每一个可能的长度,sum表示所有棍子的总长度,n表示有多上根棍子
int len[maxn];  //记录每根棍子的长度
int used[maxn]; //每根棍子是否被标记

//bool cmp(const int a, const int b)
//{
// return a>b;
//}

int cmp(const void *a ,const void *b)
{
    return *(int *)b - *(int *)a;
}
int getInt(int &x)
{
    return scanf("%d",&x);
}

bool dfs(int m,int left)//m为剩余的木棍数,left为当前正在拼接的木棍离L的距离差
{
    if(m==0&&left==0) return true;
    if(left==0)
    {
        left=L;//一根刚好拼完,给出新的初始值L
    }
    for(int i=0 ; i<n; i++)
    {
        if(!used[i]&&len[i]<=left)
        {
            if(i>0)
            {
                if(!used[i-1]&&len[i]==len[i-1])
                    continue;
            }
            used[i]=1;
            if(dfs(m-1,left-len[i]))
            {
                return true;
            }
            else
            {
                used[i]=0;//回溯
                if(left==len[i]||left==L)
                    return false;
            }
        }
    }
    return false;
}
int main()
{
    while(getInt(n)&&n)
    {
        sum=0;
        for(int i=0;i<n;i++)
        {
            getInt(len[i]);
            sum+=len[i];
        }
        bool ok=false;
        qsort(len,n,sizeof(len[0]),cmp);
        //sort(len,len+n,cmp);
        //cout<<sum<<endl;
        for(L=len[0];L<=sum/2;L++)//再往上就是一根棍子了,这里显然是一个剪枝
        {
            if(sum%L)continue;//sum%l!=0则不可能是通过长度相等的棍子裁剪而来,剪枝
            memset(used,0,sizeof(used));//每次搜索都要初始化uesd
            if(dfs(n,L))
            {
                ok=true;
                printf("%d\n",L);
                break;
            }
        }
        if(ok==false)
            printf("%d\n",sum);
    }
    return 0;
}