先从1开始遍历可能最小长度
dfs(int ct,int len,int pos) ct代表目前有的棍子总数,len代表目前这根棍子的长度,pos代表可以开始寻找棍子的位置。
矛盾主要在每一根子棍子的长度上。如果这个子棍子的长度不合理,那么要剪除所有这个长度的棍子的枝。这里有三个剪枝条件。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=70;
bool cmp(int a,int b){
return a>b;
}
int n,suma,vis[70],s[70],tar,aim,ans;
bool dfs(int ct,int len,int pos){//注意回溯!!!注意剪同样长度的枝
if(ct==tar) return true;
if(len==aim) return dfs(ct+1,0,0);
if(pos>=n) return false;
for(int i=pos;i<n;i++){
if(!vis[i]&& len+s[i] <= aim){//如果这个长度不行,跳过
vis[i]=1;
if(dfs(ct,len+s[i],pos+1)){
return true;
}
vis[i]=0;
if(len==0) return false;//如果第一就失败了,那么最长的都不行,这种方案就不行
while(i+1<n&&s[i+1]==s[i]){//如果这个长度不行,跳过这个长度
i++;
}
}
}
return false;
}
void init(){
memset(s,0,sizeof(s));
memset(vis,0,sizeof(vis));
suma=0;
for(int i=0;i<n;i++){
int temp;
scanf("%d",&temp);
suma+=temp;
s[i]=temp;
}
}
void solve(){
sort(s,s+n,cmp);
for(int i=1;i<=suma;i++){
if(!(suma%i)){
aim=i;
tar=suma/i;
if(dfs(0,0,0)){
ans=aim;
break;
}
}
}
}
int main(void){
while(scanf("%d",&n)&&n){
init();
solve();
printf("%d\n",ans);
}
}