1 题意。
2 分析。
枚举可能的最小长度,再搜索+剪枝,判断一下该最小长度是否可以由题目所给的一组子木条长度组合而成。
剪枝点:。。。
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
//const int INF=0x3f3f3f3f;
const int maxn=70;
int stick[maxn];
int visted[maxn];
int len_min;
int sum;
int flag;
int k;
void Dfs(int cur_len){
int last=0;
for(int i=k;i>=1;i--){
if(!visted[i]&&(len_min-cur_len)>=stick[i]&&stick[i]!=last){ //①
visted[i]=1;
sum-=stick[i];
if(sum==0){
flag=1;
return ;
}
cur_len+=stick[i];
int temp_cur_len=cur_len;
if(cur_len==len_min){
temp_cur_len=0;
}
Dfs(temp_cur_len);
visted[i]=0;
sum+=stick[i];
cur_len-=stick[i];
if(flag) return ;
if(!flag&&cur_len==0) return;//构建的每根原始棒的第一节不匹配则不要越过这一节处理下面的,直接返回上一层 //②
if(!flag) last=stick[i]; //①
}
}
return ;
}
int main()
{
while(~scanf("%d",&k)&&k){
sum=0;
flag=0;
for(int i=1;i<=k;i++){
scanf("%d",&stick[i]);
sum+=stick[i];
visted[i]=0;
}
sort(stick+1,stick+1+k); //③
//cout<<stick[1]<<" "<<stick[k]<<endl;
for(int i=stick[k];i<=sum-i;i++){ //④
if( (sum-i)%i==0 ){
len_min=i;
int cur_len=0;
Dfs(cur_len);
if(flag) break;
}
}
if(!flag) cout<<sum<<endl;
else cout<<len_min<<endl;
}
return 0;
}