HDU 6804 Contest of Rope Pulling (乱搞+01背包)

题意:在这里插入图片描述
题解:乱搞+01背包
原题意大概就是n个人里选和m个人里选,两者w和要相等,我们对m里的w取反即可。

如果直接按照输入dp的话,w一直为正累加会有1e6,值域太大了,我们用random_shuffle随机化一下位置,这样大概可以保证前面的w和在0附近上下浮动了。w为负,向右平移即可。这边取了40000,随机两次过了。

#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
int t, n, m, w, v;
struct node {
	int w, v;
}a[22222];
ll dp[1111111];
void cmax(ll& x, ll y) {
	if (y > x) x = y;
}
int main() {
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= n; i++) {
			scanf("%d%d", &w, &v);
			a[i] = { w, v };
		}
		for (int i = n + 1; i <= n + m; i++) {
			scanf("%d%d", &w, &v);
			a[i] = { -w, v };
		}
		n += m;
		ll ans = 0;
		random_shuffle(a + 1, a + n + 1);
		random_shuffle(a + 1, a + n + 1);
		memset(dp, -0x3f3f, sizeof(dp));
		dp[40000] = 0;
		for (int i = 1; i <= n; i++) {
			if (a[i].w > 0) {
				for (int j = 80000; j >= a[i].w; j--) cmax(dp[j], dp[j - a[i].w] + a[i].v);
			}
			else {
				for (int j = a[i].w; j <= 80000; j++) cmax(dp[j], dp[j - a[i].w] + a[i].v);
			}
			cmax(ans, dp[40000]);
		}
		printf("%lld\n", ans);
	}
	return 0;
}

你可能感兴趣的:(#,简单dp,思维)