2020 hdu多校4 1003 Contest of Rope Pulling(01背包+随机化)

题意

\(T\)组数据,有\(n\)\(m\)代表每个班级的人数,每个人有两种属性\(w_i\)(力量值),\(v_i\)(魅力值),问你从两班中选择两个子集(可为空),使得两个子集的力量值和相等,求选出来的所有人的魅力值和的最大值

解法

可以将两组人合并为一组,这里只需要将第二组的力量值改成负数就行。之后我们在dp数组上进行01背包,\(dp[0]\),就是答案。不过因为dp的时候下标可能为负数,所以需要加上一个基值代表\(0\)
因为我们所求的是恰好背包装到\(0\)的值,所以需要将整个dp数组初始化为\(-INF\), 并且每次dp的时候确保\(dp[j - w[i]]\)不为\(-INF\)(这么做可以确保dp到j的时候前面都是确实加过其他人的魅力值,而不是空的)。另外得注意一下\(w[i]\)为负数时dp的范围与方向,这只要确保\(dp[j - w[i]]\)值的更新在\(dp[j]\)之后就行,范围只要不超过数组的范围就行。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 3e3 + 7;
const ll M = 1e5 + 7;
const ll INF = 1e18;
inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}


int t;
int n, m;
struct node{
    ll w, v;
};
node a[N];
ll dp[M];

ll getdp(int n)
{
    fill(dp, dp + M, -INF);
    dp[50000] = 0;

    for (int i = 1; i <= n;i++)
    {
        if(a[i].w >= 0)
        {
            for (int j = 1e5; j >= a[i].w;j--)
            {
                if(dp[j - a[i].w] != -INF) dp[j] = max(dp[j], dp[j - a[i].w] + a[i].v);
            }
        }
        else
        {
            int lim = 1e5 + a[i].w;
            for (int j = 0; j <= lim; j++)
            {
                if (dp[j - a[i].w] != -INF) dp[j] = max(dp[j], dp[j - a[i].w] + a[i].v);
            }
        }
        
    }
    return dp[50000];
}

int main()
{
    srand(time(0));
    t = read();
    //scanf("%d", &t);
    while(t--)
    {
        n = read(), m = read();
        //scanf("%d %d", &n, &m);
        for (int i = 1; i <= n + m;i++) 
        {
            //scanf("%lld %lld", &a[i].w, &a[i].v);
            a[i].w = read(), a[i].v = read();
            if(i > n) a[i].w = -a[i].w;
        }

        random_shuffle(a + 1, a + n + m + 1);
        ll ans = 0;

        ans = getdp(n + m);

        printf("%lld\n", ans);
    }
    return 0;
}

posted @ 2020-07-31 19:55  Cyan_Cloud  阅读(230)  评论(3编辑  收藏  举报