zoukankan      html  css  js  c++  java
  • [Codeforces Round #674 (Div. 3)] E. Rock, Paper, Scissors (网络流)

    [Codeforces Round #674 (Div. 3)] E. Rock, Paper, Scissors (网络流)

    题面:

    题意:

    给定两个玩家的石头剪刀布的分别卡片个数(每一个人的卡片总和为(mathit n)),

    接下来就进行(mathit n)局游戏,每一局游戏双方(Alice and Bob ) 从自己的卡片中选出一个卡片放在桌子上,并按照常规的剪刀石头布法则觉得胜,负和平局。卡片不可回收。

    现在要计算Alice 最小可以赢多少次,和最多可以赢多少次。

    思路:

    Alice 最多可以赢多少次,这是一个经典的贪心问题,将其卡片尽量按照相克的出即可。

    主要难点在于最小可以赢多少次,有许多暴力枚举所有组合,贪心计算性质等解法,

    这里我讲解一个网络流的解法。

    这样见图:

    源点(mathit S) 对Alice的3种卡片(Rock,Paper,Scissors各自建一个节点)建立容量为卡片个数,成本为0的边。

    Alice的3种卡片节点对Bob的3种卡片节点建立容量为两个卡片个数中较小值,成本为0/1的边。

    具体规则:当Alice的卡片赢取Bob的卡片时,成本为1,否则0。

    Bob的3种卡片节点对汇点(mathit T) 建立 容量为卡片数量,成本为0的边。

    然后求出源点到汇点的最小费用最大流的费用就是Alice最小可以赢的次数。

    思路:

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <bits/stdc++.h>
    #define ALL(x) (x).begin(), (x).end()
    #define sz(a) int(a.size())
    #define rep(i,x,n) for(int i=x;i<n;i++)
    #define repd(i,x,n) for(int i=x;i<=n;i++)
    #define pii pair<int,int>
    #define pll pair<long long ,long long>
    #define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
    #define MS0(X) memset((X), 0, sizeof((X)))
    #define MSC0(X) memset((X), '', sizeof((X)))
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define eps 1e-6
    #define chu(x)  if(DEBUG_Switch) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
    #define du3(a,b,c) scanf("%d %d %d",&(a),&(b),&(c))
    #define du2(a,b) scanf("%d %d",&(a),&(b))
    #define du1(a) scanf("%d",&(a));
    using namespace std;
    typedef long long ll;
    ll gcd(ll a, ll b) {return b ? gcd(b, a % b) : a;}
    ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}
    ll powmod(ll a, ll b, ll MOD) { if (a == 0ll) {return 0ll;} a %= MOD; ll ans = 1; while (b) {if (b & 1) {ans = ans * a % MOD;} a = a * a % MOD; b >>= 1;} return ans;}
    ll poww(ll a, ll b) { if (a == 0ll) {return 0ll;} ll ans = 1; while (b) {if (b & 1) {ans = ans * a ;} a = a * a ; b >>= 1;} return ans;}
    void Pv(const vector<int> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%d", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    void Pvl(const vector<ll> &V) {int Len = sz(V); for (int i = 0; i < Len; ++i) {printf("%lld", V[i] ); if (i != Len - 1) {printf(" ");} else {printf("
    ");}}}
    inline long long readll() {long long tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') { fh = -1; } c = getchar();} while (c >= '0' && c <= '9') { tmp = tmp * 10 + c - 48, c = getchar(); } return tmp * fh;}
    inline int readint() {int tmp = 0, fh = 1; char c = getchar(); while (c < '0' || c > '9') {if (c == '-') { fh = -1; } c = getchar();} while (c >= '0' && c <= '9') { tmp = tmp * 10 + c - 48, c = getchar(); } return tmp * fh;}
    void pvarr_int(int *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%d%c", arr[i], i == n ? '
    ' : ' ');}}
    void pvarr_LL(ll *arr, int n, int strat = 1) {if (strat == 0) {n--;} repd(i, strat, n) {printf("%lld%c", arr[i], i == n ? '
    ' : ' ');}}
    const int maxn = 1000010;
    // const int inf = 0x3f3f3f3f;
    /*** TEMPLATE CODE * * STARTS HERE ***/
    #define DEBUG_Switch 0
    const int MAX_N = 200;
    const int MAX_M = 30000;
    const ll inf = 1e18;
    
    struct edge {
        int v; ll c, w; int  next; // v 表示边的另一个顶点,c 表示当前剩余容量,w 表示单位流量费用
    };
    struct MCMF {
        edge e[MAX_M];
        int p[MAX_N], s, t, eid;  // s 表示源点,t 表示汇点,需要在进行 costflow 之前设置完毕
        void init()
        {
            memset(p, -1, sizeof(p));
            eid = 0;
        }
        void insert(int u, int v, ll c, ll w)
        {
            e[eid].v = v;
            e[eid].c = c;
            e[eid].w = w;
            e[eid].next = p[u];
            p[u] = eid++;
        }
        void addedge(int u, int v, ll c, ll w)
        {
            insert(u, v, c, w);
            insert(v, u, 0, -w);
        }
        bool vis[MAX_N];
        ll d[MAX_N];  // 如果到顶点 i 的距离是 inf,则说明不存在源点到 i 的最短路
        // int - memset-> 0x3f  ll - memset-> 0x7f
        int pre[MAX_N];  // 最短路中连向当前顶点的边的编号
        bool dijk()    // 以源点 s 为起点计算单源最短路,如果不存在从 s 到 t 的路径则返回 false,否则返回 true
        {
            memset(d, 0x7f, sizeof(d));
            memset(pre, -1, sizeof(pre));
            d[s] = 0;
            priority_queue<pll, vector<pll>, greater<pll> > q;
            q.push(mp(0, s));
            while (!q.empty()) {
                pll temp = q.top();
                q.pop();
                int u = temp.se;
                if (u == t || d[u] < temp.fi) {
                    continue;
                }
                for (int i = p[u]; i != -1; i = e[i].next) {
                    if (e[i].c) {
                        int v = e[i].v;
                        if (d[u] + e[i].w < d[v]) {
                            d[v] = d[u] + e[i].w;
                            pre[v] = i;
                            q.push(mp(d[v], v));
                        }
                    }
                }
            }
            return pre[t] != -1;
        }
        ll min_cost_flow()    // 计算最小费用最大流
        {
            ll ret = 0;  // 累加和
            while (dijk()) {
                ll flow = inf;
                for (int i = t; i != s; i = e[pre[i] ^ 1].v) {
                    flow = min(e[pre[i]].c, flow);  // 计算当前增广路上的最小流量
                }
                for (int i = t; i != s; i = e[pre[i] ^ 1].v) {
                    e[pre[i]].c -= flow;     //容量是一定要跟着变化的,毕竟要继续循环使用dijk来更新下一条“能走的(看容量)”最短路。
                    e[pre[i] ^ 1].c += flow;
                    ret += e[pre[i]].w * flow;
                }
            }
            return ret;
        }
    } gao;
    int Highestscore(int n, int p1, int q1, int m1, int p2, int q2, int m2)
    {
        // write code here
        int cnt1 = min(p1, q2);
        p1 -= cnt1;
        q2 -= cnt1;
        int cnt2 = min(q1, m2);
        q1 -= cnt2;
        m2 -= cnt2;
        int cnt3 = min(m1, p2);
        m1 -= cnt3;
        p2 -= cnt3;
    
        int cnt = cnt1 + cnt2 + cnt3;
        int score = cnt;
        cnt += min(p1, p2) + min(q1, q2) + min(m1, m2);
        // score -= (n - cnt);
        return score;
    }
    int main()
    {
    #if DEBUG_Switch
        freopen("D:\code\input.txt", "r", stdin);
    #endif
        //freopen("D:\code\output.txt","w",stdout);
        int n, a1, a2, a3, b1, b2, b3;
        cin >> n;
        cin >> a1 >> a2 >> a3;
        cin >> b1 >> b2 >> b3;
        gao.init();
        gao.s = 0;
        gao.t = 7;
        gao.addedge(0, 1, a1, 0);
        gao.addedge(0, 2, a2, 0);
        gao.addedge(0, 3, a3, 0);
        gao.addedge(4, 7, b1, 0);
        gao.addedge(5, 7, b2, 0);
        gao.addedge(6, 7, b3, 0);
        gao.addedge(1, 4, a1, 0);
        gao.addedge(1, 5, a1, 1);
        gao.addedge(1, 6, a1, 0);
        gao.addedge(2, 4, a2, 0);
        gao.addedge(2, 5, a2, 0);
        gao.addedge(2, 6, a2, 1);
        gao.addedge(3, 4, a3, 1);
        gao.addedge(3, 5, a3, 0);
        gao.addedge(3, 6, a3, 0);
    
        cout << gao.min_cost_flow() << " " << Highestscore(n, a1, a2, a3, b1, b2, b3)  << endl;
        return 0;
    }
    
     
    
    本博客为本人原创,如需转载,请必须声明博客的源地址。 本人博客地址为:www.cnblogs.com/qieqiemin/ 希望所写的文章对您有帮助。
  • 相关阅读:
    python,生产环境安装
    neo4j 图数据库
    RNN系列
    机器学习关于AUC的理解整理
    fensorflow 安装报错 DEPENDENCY ERROR
    dubbo Failed to check the status of the service com.user.service.UserService. No provider available for the service
    使用hbase遇到的问题
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk
    gradle 安装
    jenkins 安装遇到的坑
  • 原文地址:https://www.cnblogs.com/qieqiemin/p/13765487.html
Copyright © 2011-2022 走看看