深搜 poj1011

题目链接:http://poj.org/problem?id=1011

本题是第深搜以及剪枝的考察,题目的大意是给了你有限个棍子以及每个棍子的长度,而且所有的棍子都是由有限个长度相同的棍子截断得到的,让你求被截棍子的最小长度,本题的算法是深搜,当然需要几个剪枝的!

剪枝一:将所有题目给的棍子的长度按照从大到小的顺序排列,然后按照此顺序进行深搜的,因为我们是按照从长度1到所有棍子的总长度进行搜的,这样从大到小可以减去一定步骤的。

剪枝二:如果第i个棍子不能拼成假设的长度,则和第i个棍子相同长度的棍子也是不可能的,所以可以直接跳过去的!

剪枝三:对于第i个棍子,如果找不到任何一个或者多个棍子和它拼成假设的长度,则说明这个假设的长度四不成力的,则直接跳过去的!

 

#include<iostream>
using namespace std;
int sum,a[100];
bool vis[100];
int cmp(const void *a,const void *b)
{
	return *(int *)b-*(int *)a;
}
int dfs(int len,int n,int stick,int ret)//应拼成的长度,帮总共的数量,已拼成的个数的
{
     if(stick==n && ret==0)//ret是代表的是以及一个棒已经拼的长度的
		 return len;//如果所有的棒都已经用完的话 
	 if(ret==0)//这代表一个已经拼完啦!
		 ret=len;
     int i;
	 for(i=0; i<n; i++)
	 {
		 if(vis[i]==true)
			 continue;
		 if(a[i]>ret)
			continue;//代表的是已经不满足题意了,直接要跳出大循环的
		 vis[i]=true;
		 if(dfs(len,n,stick+1,ret-a[i])) 
			 return len;
		 vis[i]=false; 
		 if(ret==a[i] || len==ret)//最重要的剪枝,如果找不到任意一个枝和当前的枝进行匹配,则说明不可能对了,就直接跳出大循环的!
			 break;
		 while(a[i]==a[i+1])//剪枝三,第i根没有拼成的话,第i+1根和第i根长度相同的话也就拼不成了,剪去的
			 i++;
	 }
	 return 0;
}
int main()
{
	int i,j,n,k;
	while(1)
	{
		cin>>n;
		if(n==0)
			break;
		sum=0;
		for(i=0; i<n; i++)
		{
			cin>>a[i];
			sum+=a[i];
		}
		qsort(a,n,sizeof(int),cmp);//剪枝一,按照棍子从大到小排列的,然后直接舍弃总棍子太小的
		for(i=1; i<=sum; i++)
		{
			if(sum%i!=0)
				continue;//本来就不可以的啊
			for(j=0; j<n; j++)
				vis[j]=false;//初始化的
		    k=dfs(i,n,0,i);
			if(k!=0)
				break;
		}
		cout<<k<<endl;
	}
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

淡定的小Y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值