zoukankan      html  css  js  c++  java
  • POJ 1015 Jury Compromise (算竞进阶习题)

    01背包

    我们对于这类选或者不选的模型应该先思考能否用01背包来解。
    毫无疑问物体的价值可以看成最大的d+p值,那么体积呢?题目的另一个限制条件是d-p的和的绝对值最小,这启发我们把每个物体的d-p的值当作体积。

    可以尝试设计状态f[i, j, k]表示从前i个物品中选j个,体积是k的最大价值。
    同样的,我们可以用滚动数组的方法把第一维i去掉。
    那么得到状态转移方程:

    f[j, k] = max(f[j - 1, k - d[i] - p[i]] + d[i] + p[i], f[j, k])

    对于j这一维,用倒序即可保证状态的更新.

    但是这里的体积可能是负数,为了保证下标为正数,我们可以先整体右移下标的区间,最后从重心两边寻找最近点即可找到体积差最小的状态。

    #include <iostream>
    #include <cstdio>
    #include <vector>
    #include <cstring>
    #define INF 0x3f3f3f3f
    #define full(a, b) memset(a, b, sizeof a)
    using namespace std;
    typedef long long ll;
    inline int lowbit(int x){ return x & (-x); }
    inline int read(){
        int X = 0, w = 0; char ch = 0;
        while(!isdigit(ch)) { w |= ch == '-'; ch = getchar(); }
        while(isdigit(ch)) X = (X << 3) + (X << 1) + (ch ^ 48), ch = getchar();
        return w ? -X : X;
    }
    inline int gcd(int a, int b){ return a % b ? gcd(b, a % b) : b; }
    inline int lcm(int a, int b){ return a / gcd(a, b) * b; }
    template<typename T>
    inline T max(T x, T y, T z){ return max(max(x, y), z); }
    template<typename T>
    inline T min(T x, T y, T z){ return min(min(x, y), z); }
    template<typename A, typename B, typename C>
    inline A fpow(A x, B p, C lyd){
        A ans = 1;
        for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd;
        return ans;
    }
    const int N = 305;
    int a[N], b[N], dp[N][8005];
    vector<int> p[N][8005];
    int main(){
    
        int n, m, _ = 0;
        while(~scanf("%d%d", &n, &m) && n && m){
            for(int i = 0; i <= N - 1; i ++)
                for(int j = 0; j < 1000; j ++)
                    p[i][j].clear();
            for(int i = 1; i <= n; i ++){
                int x = read(), y = read();
                a[i] = x - y, b[i] = x + y;
            }
            full(dp, 0xcf);
            int now = 20 * m; dp[0][now] = 0;
            for(int i = 1; i <= n; i ++){
                for(int j = m; j >= 1; j --){
                    for(int k = 2 * now; k >= a[i]; k --){
                        if(dp[j][k] < dp[j - 1][k - a[i]] + b[i]){
                            dp[j][k] = dp[j - 1][k - a[i]] + b[i];
                            p[j][k] = p[j - 1][k - a[i]];
                            p[j][k].push_back(i);
                        }
                    }
                }
            }
            int i = 0;
            for(; dp[m][i + now] < 0 && dp[m][now - i] < 0; i ++);
            int k = dp[m][i + now] > dp[m][now - i] ? i : -i;
            int sumd = (dp[m][now + k] + k) / 2, sump = (dp[m][now + k] - k) / 2;
            printf("Jury #%d 
    ", ++_);
            printf("Best jury has value %d for prosecution and value %d for defence:
    ", sumd, sump);
            for(int j = 0; j < p[m][now + k].size(); j ++){
                printf(" %d", p[m][now + k][j]);
            }
            printf("
    ");
        }
        return 0;
    }
    
  • 相关阅读:
    bzoj1415 NOI2005聪聪和可可
    Tyvj1952 Easy
    poj2096 Collecting Bugs
    COGS 1489玩纸牌
    COGS1487 麻球繁衍
    cf 261B.Maxim and Restaurant
    cf 223B.Two Strings
    cf 609E.Minimum spanning tree for each edge
    cf 187B.AlgoRace
    cf 760B.Frodo and pillows
  • 原文地址:https://www.cnblogs.com/onionQAQ/p/10754152.html
Copyright © 2011-2022 走看看