2020寒假集训专题一搜索E题 POJ - 1011

2020寒假集训专题一搜索E题POJ - 1011

原题链接:http://poj.org/problem?id=1011
专题链接:https://vjudge.net/contest/347799#problem/E

思路

本题看似无从下手,但稍微想想就能明白,答案必须为所有木棍长度总和的约数,这让dfs的做法成为了可能,我们先将小木棍降序排序,从最大的木棍的长度向上枚举即可。

但本题真正难的地方在于剪枝,最重要的一个剪枝在于——在判断了一个木棍不合题意后,其它与其长度相同的木棍肯定也是不符合题意的,因此,我们在将木棍按长度排序后,可以建一个数组n,用于存放与其长度不同的下一个木棍的位置,这样,我们再得知某一个木棍不合题意时可以自己tp到下一个有价值的木棍去,免去了大量的重复工作。

AC代码如下

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include <stack>
using namespace std;
int N,sum;
int arr[67];
int flag[67];//用于标记小木棍是否被用过
int n[67];//用于记录下一个不同长度的木棍的位置
int t;
int co;
bool cam(int a, int b)
{
	return a > b;
}
bool dfs(int nowpan, int k, int waitget, int wait)//分别表示现在判断的是否能作为答案的大木棍的长度,现在判断是否要取的小木棍的下标,要凑成大木棍的剩余长度,还剩下几根未取的小木棍
{	
	if ((waitget == 0) && (wait == 0))//当待取长度和剩余小木棍都为0时合题意
		return 1;
	if (waitget == 0)
	{
		waitget =nowpan;
		k = 1;
	}
	for(;k<=co&&k!=0;k++)//这里k!=0用来让使用n数组tp时,最后面几个没有下一个不同长度的木棍能正常结束,而不是在搜索一遍浪费时间(因为这几个元素未被赋值,指向的是0)
	{
		if (flag[k] != 0)//用过的小木棒肯定不能再用
			continue;
		if (waitget - arr[k] < 0)//满足此条件说明这个长度的小木棒不能用,直接tp到下一个长度不一样的小木棍那里
		{
			k = n[k];
		}
		else
		{
			flag[k] = 1;
			if (dfs(nowpan, k+1, waitget - arr[k], wait-1)==1)
				return 1;		
			flag[k] = 0;//如果能到这里的话,表示取arr【i】不成立,根据此信息进行回溯+剪枝
		   k = n[k];////能到这里说明这个长度不可用,直接tp到下一个长度不一样的小木棍那里
		}
	}
	return 0}
int main()
{
	while (cin >> N)
	{
		memset(arr, 0, sizeof(arr));
          if (N == 0)
			break;
		sum = 0;
		co = 0;
		for (int i = 1; i <= N; i++)
		{
			scanf("%d", &t);
			if (t <= 50)//用于过滤小木棍长度大于50的
			{	++co;
				arr[co] = t;
				sum += arr[co];
			}
		}
		sort(arr + 1, arr + co+1,cam);//对木棍进行降序排序
		memset(n, 0, sizeof(n));
		for (int i = 1;i< co; i++)//用于寻找下一个不同长度的小木棒的位置
		{
			if (arr[i] != arr[i + 1])
			{
				t =i+1 ;
				for (int j = i; n[j] == 0 && j >=1; j--)
				{
					n[j] = t;	
				}
			}
		}
		for (int i = 0;; i++)//从最大小木棍的长度开始枚举
		{
			if (sum % (arr[1] + i) != 0)//答案必须为所有木棍长度总和的约数
				continue;
			memset(flag, 0, sizeof(flag));
			if (dfs(arr[1] + i,1, arr[1]+i,co))
			{
				printf("%d\n",arr[1]+i);
				break;
			}
		}
	}
	return 0;
}
发布了6 篇原创文章 · 获赞 0 · 访问量 196

猜你喜欢

转载自blog.csdn.net/bllovepigpig/article/details/103964088