核心思想:dfs + 剪枝
暴搜 : 将所有木棒从大到小排序 搜索
剪枝 : 失败后 注意一定是当前木棍失败后**(无解)**

#include
#include
#include
using namespace std;
const int N = 70;
int n;
bool st[N];
int w[N];
int sum,len;
bool dfs(int u,int cur,int start) //u为长木棍数量 cur为当前长木棍长度 start为当前木棍编号
{
if(u * len == sum) return true; //全部拼出来
if(cur == len) return dfs(u+1,0,0); //当前这根拼完
for(int i=start;i<n;i++)
{
if(st[i]) continue; //被搜过
if(cur+w[i] <= len)
{
st[i] = true;
if(dfs(u,cur+w[i],i+1)) return true;
st[i] = false; //恢复现场
}
//失败后
if(!cur || cur + w[i] == len) return false; //2 3剪枝
int j = i+1;
while(j<n && w[i] == w[j]) j++; //1剪枝
i = j-1;
}
return false;
}
int main()
{
while(cin>>n , n)
{
sum = len = 0;
for(int i=0;i<n;i++)
{
cin>>w[i];
sum += w[i];
len = max(len,w[i]); //取最长木棍
}
sort(w,w+n,greater<int>());
memset(st,0,sizeof st);
while(true)
{
if(sum % len == 0 && dfs(0,0,0)) //len从最长小木棍开始++
{
cout<<len<<endl;
break;
}
len++;
}
}
return 0;
}