题目:http://acm.hdu.edu.cn/showproblem.php?pid=1455
题意:给一些木条长度,原本是相同长度的木条掰断而成,求重新组成的最短长度;
思路:还是dfs暴力枚举,枝剪一些就行,虽然前后一起找快一些,但不会写。
#include<bits/stdc++.h>
using namespace std;
int a[65],sum,num,lenn,n,ans;
bool flg[65];
bool cmp(int a,int b){
return a>b;
}
bool dfs(int cnt,int len,int pos){
if(cnt==num) return true;
if(len==lenn) return dfs(cnt+1,0,0);
for(int i=pos;i<n;i++){
if(!flg[i]&&len+a[i]<=lenn){
flg[i]=true;
if(dfs(cnt,len+a[i],i+1))
return true;
flg[i]=false;
if(len == 0) return false; //关键一步,第一根匹配失败的这种长度必然就不行
while(i+1<n&&a[i+1]==a[i]) i++; //与失败的木条长度相同的剪掉
}
}
return false;
}
int main(){
while(scanf("%d",&n)&&n){
sum=0;
memset(a,0,sizeof(a));
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
sum+=a[i];
}
sort(a,a+n,cmp);
for(int i=a[0];i<=sum;i++){
if(((double)sum/i-(int)(sum/i))!=0) continue;
memset(flg,0,sizeof(flg)); //又忘了,每次dfs都该清零的
num=sum/i;lenn=i;
if(dfs(0,0,0)){
ans=lenn;
break;
}
}
cout<<ans<<endl;
}
return 0;
}