D - Sticks POJ - 1011 (dfs+剪枝)

George took sticks of the same length and cut them randomly until all parts became at most 50 units long. Now he wants to return sticks to the original state, but he forgot how many sticks he had originally and how long they were originally. Please help him and design a program which computes the smallest possible original length of those sticks. All lengths expressed in units are integers greater than zero.
Input
The input contains blocks of 2 lines. The first line contains the number of sticks parts after cutting, there are at most 64 sticks. The second line contains the lengths of those parts separated by the space. The last line of the file contains zero.
Output
The output should contains the smallest possible length of original sticks, one per line.
Sample Input
9
5 2 1 5 2 1 5 2 1
4
1 2 3 4
0
Sample Output
6
5

自己死活写不出来系列,刚开始写的时候进入了误区,以为确定过原长度后,从大的开始往前找如果+a[i]<=原长度就塞进去,后来发现不对。。。5 3 3 3 2 2 当原长度为9时,(5 2 2)(3 3 3)但5+3后就判断不对。然后就GG了。看了解析后了解到需要用dfs每个都试一试才能试出来。。。(其实剪枝才是重点。。。

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int a[1000],b[1000],n;
int cmp(int x,int y)
{
	return x>y;
}
int dfs(int len,int need,int left)//len原长度need还需要多少到len,left剩余的棒
{
	if(need==0&&left==0)
		return len;
	if(need==0)
		need=len;
	for(int i=0;i<n;i++)
	{
		if(b[i]==1) 
		continue;
		if(need>=a[i])
		{
			b[i]=1;
			if(dfs(len,need-a[i],left-1))
			return len;
			b[i]=0;
		}
		if(len==need||need==a[i])//a[i]不行了如果len==need,a[i]无法拼成len 
		break;
		while(a[i]==a[i+1])//a[i]不行和a[i]相同的也不行 
		i++;
	}
	return 0;
}
int main()
{
	while(scanf("%d",&n),n!=0)
	{
		int x=0,y=0;
		for(int i=0;i<n;i++)
		{
			scanf("%d",&a[i]);
			if(a[i]>x)
			x=a[i];
			y+=a[i];
		}
		sort(a,a+n,cmp);
		for(int i=x;i<=y;i++)
		{
			memset(b,0,sizeof(b));
			int ans=0;
			if(y%i==0)
			{
				ans=dfs(i,i,n);
			}
			if(ans)
			{
				printf("%d\n",ans);
				break;
			 } 
		}
	}
	return 0;
 } 


猜你喜欢

转载自blog.csdn.net/liuliu2333/article/details/80764687