HDU 1455 Sticks
非常经典的搜索剪枝,剪枝说明见程序:
#include <cstdio>
#include <algorithm>
using namespace std;
int l,total,n,sum;
struct node{
int l;
bool flag;
friend bool operator < (const node &a,const node &b){
return a.l>b.l;
}
}stick[100];
bool dfs(int s,int nl,int pos){
if(s==total-1)return true;
//最后一根不必搜,因为加起来一定为l
for(int i=pos+1;i<=n;i++){
//记录上一次搜到的地方,不要从第一个重新开始搜
if(stick[i].flag)continue;
if(nl+stick[i].l==l){
stick[i].flag=true;
if(dfs(s+1,0,0))return true;
//下一根则需要重新搜索
stick[i].flag=false;
return false;
}
else if(stick[i].l+nl<l){
stick[i].flag=true;
if(dfs(s,nl+stick[i].l,i))return true;
stick[i].flag=false;
if(nl==0)return false;
//如果第一根都无法用上,一定是失败的
while(stick[i].l==stick[i+1].l)i++;
//避免重复搜索同一根
}
}
return false;
}
int main(){
while(scanf("%d",&n),n!=0){
sum=0;
for(int i=1;i<=n;i++){
scanf("%d",&stick[i].l);
sum+=stick[i].l;
stick[i].flag=false;
}
sort(stick+1,stick+n+1);//排序加速
for(l=stick[1].l;l<=sum;l++)
//从最长的作为循环的开始,而不是1,因为不可能比其小
if(sum%l==0){
//注意可以组成sum的最小长度一定是sum的约数
total=sum/l;
if(dfs(0,0,0)){
printf("%d\n",l);
break;
}
}
}
return 0;
}
愿你出走半生,归来仍是少年

浙公网安备 33010602011771号