poj 1014 Dividing

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

题目大意:告诉价值为1、2、3、4、5、6的物品各有几件,判断两人能否平分。

题目分析:方法很多,比如二进制多重背包、抽屉原理、dfs(需要预处理),不过我还是暂时没有考虑优化的问题,代码大概要跑60ms左右。注意剪枝和输出格式。

代码参考:

#include<cstdio>
#include<cstring>
char dp[60001];//实际上是bool型,判断能否放满i价值的物品
int mar[7];
int main()
{
	int c = 0;//测试数据组数
	while(++c)
	{
		int i, j, k, pos, sum = 0;
		for(i=1; i<=6; ++i)
		{
			scanf("%d", &mar[i]);//为每种价值的物品数量
			sum += mar[i]*i;//sum为总价值
		}
		if(sum == 0) break;//如果输入的都是“0”的话就退出
		//剪枝 
		if(sum & 1)//如果总数不是偶数的话肯定无法平均分配 
		{
			printf("Collection #%d:\nCan't be divided.\n\n", c);
			continue;//以下步骤不再进行
		}
		sum >>= 1;;//看一半的价值能否放满一半的背包 
		memset(dp, 0, sizeof(dp));
		dp[0] = 1;//什么都不放时背包里总价值为0, 因此此状态能达到
		for(i=6; i>0; --i)//枚举六种价值的物品
		{
			for(j=sum; j>=0; --j)//枚举能否放满j价值的物品
			{//如果放满j价值的物品的状态无法达到,或者达到了能放满j+i价值的物品,则不能继续往下推
				if(dp[j] == 0 || dp[j+i] == 1)  continue;
				pos = j;
				for(k=0; k<mar[i]; ++k)//枚举每种价值的物品数量
				{
					pos += i;//每放入一件i价值的物品
					if(pos > sum)  break;//如果已经超过一半的价值了,则退出
					dp[pos] = 1;//此状态能达到
				}
			}
		}//输出答案,注意格式
		printf("Collection #%d:\n", c);
		if(dp[sum] == 1)  puts("Can be divided.\n");
		else puts("Can't be divided.\n");
	}
	return 0;
}


ps:测试数据:

输入:

1 0 1 2 0 0

1 0 0 0 1 1

2 0 0 3 0 0

1 1 1 1 1 1

0 6999 0 6001 0 7000

0 0 0 0 4 5

3333 3333 3333 3333 3333 3333

0 0 0 1 0 2

1 2 3 4 5 6

0 0 0 0 4 5

0 0 2 3 0 0

0 0 0 2 2 1

0 0 0 1 2 2

0 1 2 3 4 5

6 5 4 3 2 1

0 0 5 0 3 0

0 3 0 0 0 1

0 2 0 1 0 0

1 1 1 0 0 0

3334 3334 3333 3333 3333 3333

0 1 1 1 1 1

0 0 0 0 6 5

0 0 0 3 0 2

0 0 1 3 3 4

0 0 0 1 4 6

0 0 0 1 4 5

0 0 0 0 0 0

答案:

Collection #1:
Can't be divided.


Collection #2:
Can be divided.


Collection #3:
Can't be divided.


Collection #4:
Can't be divided.


Collection #5:
Can't be divided.


Collection #6:
Can't be divided.


Collection #7:
Can't be divided.


Collection #8:
Can't be divided.


Collection #9:
Can't be divided.


Collection #10:
Can't be divided.


Collection #11:
Can't be divided.


Collection #12:
Can't be divided.


Collection #13:
Can't be divided.


Collection #14:
Can be divided.


Collection #15:
Can be divided.


Collection #16:
Can be divided.


Collection #17:
Can be divided.


Collection #18:
Can be divided.


Collection #19:
Can be divided.


Collection #20:
Can be divided.


Collection #21:
Can be divided.


Collection #22:
Can be divided.


Collection #23:
Can be divided.


Collection #24:
Can be divided.


Collection #25:
Can be divided.


Collection #26:
Can be divided.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值