2019暑期集训-【HDU 1171】多重背包转01背包 Big Event in HDU

题目链接:传送门

题意:

样例:

2

10 1

20 1

意思是两种物品,质量为10的物品有一个,质量为20的物品有一个,求如何分使得最大程度的两等分

答案当然是  : 20   10   (题目规定大的放前面)

3

10 1

20 2

30 1 

意思是三种物品,质量为10的物品有一个,质量为20的物品有两个,,质量为30的物品有一个,求如何分使得最大程度的两等分

答案当然是  : 40   40  即20 20放一起   、10 30 放一起即可 

分析:本题我采用多重背包转01背包的做法,把输入的物品质量放入a数组,如果物品数量大于1,就放多次,当然可以二进制优化,但在本题中不优化也可以AC。

另外注意判断输入结束必须是t<0 ,而不是t==-1!!!

另外注意判断输入结束必须是t<0 ,而不是t==-1!!!

另外注意判断输入结束必须是t<0 ,而不是t==-1!!!

当然下面就是01背包的模板

for i=1..N
    for v=V..0
        f[v]=max{f[v],f[v-c[i]]+w[i]};

在本题中,第一层遍历物品的个数N,第二层遍历背包容量sum/2,状态转移方程一套就可以了。

注意dp数组的初始化,还有输出大的放前面即可。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[5002];
int dp[500002];
int maxx(int x, int y) {
	return x > y ? x : y;
}
int main()
{
	int t;
	while (~scanf_s("%d", &t) && t >= 0) {
		int len = 0;
		int sum = 0;
		while (t--) {
			int x, y;
			scanf_s("%d%d", &x, &y);
			sum += x * y;
			while (y--) {
				a[len++] = x;
			}
		}
		int summ = sum;
		sum /= 2;
		memset(dp, 0, sizeof(dp));
		for (int i = 0; i < len; i++) {
			for (int j = sum; j >= a[i]; j--) {
				dp[j] = maxx(dp[j], dp[j - a[i]] + a[i]);
			}
		}
		printf("%d %d\n", summ - dp[sum], dp[sum]);
	}
	return 0;
}
发布了42 篇原创文章 · 获赞 26 · 访问量 9586

猜你喜欢

转载自blog.csdn.net/qq_41464123/article/details/95641879
今日推荐