zoukankan      html  css  js  c++  java
  • POJ 1015 Jury Compromise 2个月后重做,其实这是背包题目

    http://poj.org/problem?id=1015

    题目大意:在遥远的国家佛罗布尼亚,嫌犯是否有罪,须由陪审团决定。陪审团是由法官从公众中挑选的。先随机挑选n个人作为陪审团的候选人,然后再从这n个人中选m人组成陪审团。选m人的办法是:控方和辩方会根据对候选人的喜欢程度,给所有候选人打分,分值从0到20。为了公平起见,法官选出陪审团的原则是:选出的m个人,必须满足辩方总分和控方总分的差的绝对值最小。如果有多种选择方案的辩方总分和控方总分的之差的绝对值相同,那么选辩控双方总分之和最大的方案即可。

    其实学DP首先要从背包开始,学了背包后,看这题就是一个背包 + 记录路径的问题

    设dp[m][k] = max表示,选了m个数,产生的和差值是k的时候,的最大和值。

    但是,这个背包是不能记录路径的,

    因为

    2 2

    1 2

    3 4

    这组数据,生成和差值是-1的时候有两个,这样会存在路径覆盖问题。

    所以要这样做,暴力枚举m组,对于每一次,都在1---n中选一个,然后选的时候看看是否存在于这条路径就行了。

    也就是对于上面的数据,一开始选解出选出1个的时候的最优值,那自然是选第二个数,然后,再解出选出两个数的时候的最优解。

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <assert.h>
    #define IOS ios::sync_with_stdio(false)
    using namespace std;
    #define inf (0x3f3f3f3f)
    typedef long long int LL;
    
    
    #include <iostream>
    #include <sstream>
    #include <vector>
    #include <set>
    #include <map>
    #include <queue>
    #include <string>
    int n, m;
    const int fix = 20;
    const int maxn = 200 + 20;
    struct node {
        int b, c, dis, sum;
    }a[maxn];
    const int up = 40 * 20 + 20;
    struct DP {
        int is, pre;
        int id, val;
    }dp[20 + 20][up];
    set<int>ans;
    bool in(int go, int val, int cmp) {
        while (go > 0) {
            if (dp[go][val].is == -1) return false;
            if (dp[go][val].id == cmp) return true;
            val = dp[go][val].pre;
            assert(val <= up);
            assert(val >= 0);
            go--;
        }
        return false;
    }
    void work() {
    //    init();
        for (int i = 1; i <= n; ++i) {
            scanf("%d%d", &a[i].b, &a[i].c);
            a[i].dis = a[i].b - a[i].c + fix;
            a[i].sum = a[i].b + a[i].c;
        }
        memset(dp, -1, sizeof dp);
        dp[0][0].id = inf, dp[0][0].is = 0, dp[0][0].pre = inf, dp[0][0].val = 0;
        for (int i = 1; i <= m; ++i) { //选m个
            for (int j = 1; j <= n; ++j) {
                for (int k = a[j].dis; k <= up - 20; ++k) {
                    if (dp[i - 1][k - a[j].dis].is == -1) continue;
                    if (dp[i][k].val < dp[i - 1][k - a[j].dis].val + a[j].sum && !in(i - 1, k - a[j].dis, j)) {
    //                    if (dp[i][k].id == j) continue;
                        dp[i][k].val = dp[i - 1][k - a[j].dis].val + a[j].sum;
                        dp[i][k].is = 0;
                        dp[i][k].id = j;
                        dp[i][k].pre = k - a[j].dis;
                    }
                }
            }
        }
        int p1 = m * fix, p2 = m * fix;
        int id1 = -inf, id2 = -inf, idans = -inf;
        while (true) {
            if (dp[m][p1].is != -1) id1 = p1;
            if (dp[m][p2].is != -1) id2 = p2;
            if (id1 != -inf && id2 == -inf) {
                idans = id1;
                break;
            } else if (id1 == -inf && id2 != -inf) {
                idans = id2;
                break;
            } else if (id1 != -inf && id2 != -inf) {
                if (dp[m][id1].val > dp[m][id2].val) {
                    idans = id1;
                } else idans = id2;
                break;
            }
            p1--;
            p2++;
        }
    //    cout << idans << endl;
        ans.clear();
        int go = m;
        while (dp[go][idans].id != inf) {
            assert(dp[go][idans].is != -1);
            ans.insert(dp[go][idans].id);
            idans = dp[go][idans].pre;
            go--;
        }
        static int f = 0;
        printf("Jury #%d
    ", ++f);
        int ans1 = 0, ans2 = 0;
        for (set<int> :: iterator it = ans.begin(); it != ans.end(); ++it) {
            ans1 += a[*it].b;
            ans2 += a[*it].c;
        }
    //    cout << endl;
        printf("Best jury has value %d for prosecution and value %d for defence:
    ", ans1, ans2);
        for (set<int> :: iterator it = ans.begin(); it != ans.end(); ++it) {
            cout << " " << *it;
        }
        cout << endl;
    }
    
    int main() {
    #ifdef local
        freopen("data.txt", "r", stdin);
    //    freopen("data.txt", "w", stdout);
    #endif
        while (scanf("%d%d", &n, &m) != EOF && (n + m)) {
            work();
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    会计科目不能使用
    SAP提示为创建科目作为控制范围中成本要素
    创建成本要素
    拓端tecdat:R语言集成模型:提升树boosting、随机森林、约束最小二乘法加权平均模型融合分析时间序列数据
    拓端tecdat:R语言用贝叶斯线性回归、贝叶斯模型平均 (BMA)来预测工人工资
    拓端tecdat:数据评估三方科技公司开发人员能力
    拓端tecdat:R语言因子实验设计nlme拟合非线性混合模型分析有机农业施氮水平
    拓端tecdat:R语言主成分回归(PCR)、 多元线性回归特征降维分析光谱数据和汽车油耗、性能数据
    Go的异常处理 defer, panic, recover
    Android项目架构设计深入浅出
  • 原文地址:https://www.cnblogs.com/liuweimingcprogram/p/6257624.html
Copyright © 2011-2022 走看看