Poj 1014简单dfs

30 篇文章 0 订阅

传送门:POJ1014

题意:给你1-6六个数,分别有不一定的数量,问你能不能凑成和相等的两部分。

其实这个题真的很水啊,真的真的很水啊,可是月赛的时候愣是让三个人TLE的一晚上,想尽办法剪枝,又剪成了WA。。最后赛完发现是回溯的问题。。。这题根本不用回溯。。带上回溯必定超时,不回溯的原因是:dfs的时候已经保证了每次加入一个新数时不能超过sum/2,所以只需要一口气搜到底就好了,如果这次拼不成,就算再回溯也肯定拼不成,这里做个假设要拼凑的数为sum/2==30,那么前18用越大的数来拼越好(优先级6>5>4...),因为较小的数要留下来处理边界情况,后12数越小边界情况越有可能处理成功,因此如果回溯用另外一些小的数去拼凑这里的18,后面就更不可能拼成了。

理解不了也可以感性思考一下,因为我们是去dfs拼凑两部分之一,那么这一堆里没有的数就是要扔给另一堆的,你这一堆用这些数都拼不成,在回溯的时候把这些数扔给另一堆,那另一堆肯定也拼不成啊。。

写这篇博客来纪念一下一晚上的TLE吧。。

下面是正确代码:

#include<stdio.h>
#define n 6
int sum;
int num[6],k=0,flag;
int dfs(int s)//s是已经凑出来的数的和
{	
	if(s==sum||flag)
	{
		flag=1;
		return 0;
	}
	for(int i=5;i>=0;i--)
	{
		if(num[i]&&(s+i+1)<=sum)
		{
		
			num[i]--;
			dfs(s+(i+1));
			if(flag)
			return 0;
			
		}//千万不要回溯
	}
}
int main()
{
	
	int i;
	while(~scanf("%d",&num[0]))
	{	
	flag=0;
	sum=0;
		k++;
		for(i=1;i<6;i++)
		scanf("%d",&num[i]);
		for(i=0;i<6;i++)
		{
			sum+=num[i]*(i+1);
		}
		if(sum==0)
		break;
		printf("Collection #%d:\n",k);
		if(sum%2==0)
		{
			sum/=2;
			dfs(0);
			if(flag)
			printf("Can be divided.\n");
			else
			printf("Can't be divided.\n");
		}
		else
		{
			printf("Can't be divided.\n");
		}
		printf("\n");
	}
	
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值