您的位置:首页 > 其它

POJ_1011_Sticks

2010-07-12 19:00 316 查看
////搜索剪枝,一个好的剪枝真的是太关键了,对剪枝有了进一步了解
///先深度搜索出一只原始木棍,将用到的小木棍标识为已经使用,在这个基础上再深度搜索下
///一只原始木棍,分层深度搜索(自己想的名字),最后根据是否得到了目标数目的原始木棍来判断
///程序是否结束。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<time.h>
using namespace std;
int f[70],stick[70];
int n,t,flag;
int cmp(const void* _a,const void* _b)
{
int* a=(int *)_a;
int* b=(int *)_b;
return -(*a-*b);
}
//ti:已经组合成长度p的木棍的数目。total:已匹配的小木棍加起来的长度,begin:下一根小木棍
//从何处开始匹配。
int dfs(int ti,int p,int total,int begin)
{
//flag为1则表示已经成功匹配了所有小木棍,并能够得到结果。
if(ti==t)
{
flag=1;return 1;
}
if(flag)
return 1;
int i,j,last;
//剪枝3:last保存本次循环(不会传到子函数中)中上次处理的木棍长度,主要是避免相同长度的木棍
//重复问题
for(i=begin,last=-1;i<n;i++)
{
if(!f[i]&&stick[i]!=last)
{
if(stick[i]<p-total)
{
last=stick[i];
f[i]=1;
dfs(ti,p,total+stick[i],i+1);
f[i]=0;
}
if(stick[i]==p-total)
{
last=stick[i];
f[i]=1;
dfs(ti+1,p,0,0);
f[i]=0;
}
if(flag)
return 1;
///缺少了下面的判断要多出很多不必要的计算,相当关键
/***************************/
if(begin==0)
return 0;
/***************************/
}
}
return 0;
}
///判断是否能够组合成数根原始长度为p的木棍,能返回1,否则返回0
int isok(int p)
{
memset(f,0,sizeof(f));
flag=0;
if(dfs(0,p,0,0))
return 1;
else
return 0;
}
//n为木棍数目,stick[]存储的是木棍长度,sum所有木棍总长度
int main()
{
freopen("in.txt","r",stdin);
freopen("ou2.txt","w",stdout);
while(scanf("%d",&n)==1&&n)
{
int i,sum=0;
for(i=0;i<n;i++)
{
scanf("%d",&stick[i]);
sum+=stick[i];
}
//剪枝1:木棍由大到小排列,长度大的木棍比长度小的木棍更有用,可以减少搜索深度
qsort(stick,n,sizeof(stick[1]),cmp);
for(i=stick[0];;i++)///initial最小长度为所给木棍的最大长度
{
t=sum/i;///t保存原始木棍的数目
///剪枝2:木棍总长度必为原始木棍长度的倍数
if(sum%i==0&&isok(i))
break;
}
printf("%d  %f/n",i,(double)clock()/CLOCKS_PER_SEC);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: