二维背包(钟神设下的陷阱)

【问题描述】

背包是个好东西,希望我也有。
给你一个二维的背包,它的体积是???? × ????。现在你有一些大小为1 × 2和1 ×
3的物品,每个物品有自己的价值。你希望往背包里面装一些物品,使得它们的
价值和最大,问最大的价值和是多少。

【输入格式】

第一行一个整数????代表该测试点的数据组数。
对于每组数据,第一行有四个整数????, ????, ????
1
, ????
2,其中????
1
, ????
2分别代表大小为
1 × 2和大小为1 × 3的物品个数。
接下来一行有????
1
个数代表每个1 × 2物品的价值。
接下来一行有????
2
个数代表每个1 × 3物品的价值。

【输出格式】

对于每组询问,输出能够达到的价值最大值。

【样例输入】

1
2 3 2 2
1 2
1 2

【样例输出】

4

【样例解释】

庙里有座山。

【数据规模与约定】

对于20%的数据,????, ???? ≤ 10, ????1, ????2≤ 100。
对于70%的数据,????, ???? ≤ 100, ????1, ????2≤ 2000。
对于100%的数据,1 ≤ ???? ≤ 10,1 ≤ ????, ???? ≤ 500,0 ≤ ????1, ????2≤ 10000。

题解:

这道题看似背包型DP,其实不是,因为数据范围不允许,所以我们用贪心的思想来做(人生第一次用DP来骗贪心的分)
我们枚举放k个2个的块和n1+n2-k个3个的块,然后取最大值
就得到了答案

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int II[233333], III[233333];
bool cmp(int a, int b)
{
	return a > b;
}
int main()
{
	freopen("eyesight.in","r",stdin);
	freopen("eyesight.out","w",stdout);
	int t;
	cin >> t;
	while (t--)
	{
		int n, m, n1, n2;
		cin >> n >> m >> n1 >> n2;
		int s = n*m;
		for (int i = 1; i <= n1; i++)
			scanf("%d", &II[i]);
		for (int i = 1; i <= n2; i++)
			scanf("%d", &III[i]);
		if (n <= 1 && m <= 1)
			memset(II, 0, sizeof(II));
		if (n <= 2 && m <= 2)
			memset(III, 0, sizeof(III));
		sort(II + 1, II + n1 + 1, cmp);
		sort(III + 1, III + n2 + 1, cmp);
		for (int i = 1; i <= n1; i++)
			II[i] += II[i-1];
		for (int i = 1; i <= n2; i++)
			III[i] += III[i-1];
		int ans = 0;
		for (int i = 1; i <= n1 && (i << 1) <= s; i++)
			ans = max(ans, II[i] + III[min((s - i * 2) / 3, n2)]);
		printf("%d\n", ans);
	}
	return 0;
}

 

上一篇
下一篇