Codeforces Round #674 E. Rock, Paper, Scissors【数学 | 最大流 | 思维】

18 篇文章 0 订阅
2 篇文章 0 订阅

题目链接

题目描述

A 和 B 进行石头剪刀布游戏,共进行 n 个回合,其中 A 出 a 1 a_1 a1 次石头, a 2 a_2 a2 次剪刀, a 3 a_3 a3 次布,B 出 b 1 b_1 b1 次石头, b 2 b_2 b2 次剪刀, b 3 b_3 b3 次布,问 A 最多获胜的次数和最少获胜的次数。


最大流做法:

min:

You can link the source to A’s options (2-rock, 3-scissors, 4-paper) with their respectives capacities ( a 1 a_1 a1, a 2 a_2 a2, a 3 a_3 a3) and the sink to Bob’s ones (5-rock, 6-scissors, 7-paper) with capacities ( b 1 b_1 b1, b 2 b_2 b2, b 3 b_3 b3). Then link the options that make A not win (draw or lose) with infinite capacity and just calculate the max flow in that network. The edges will be: (source, 2), (source, 3), (source, 4), (2, 5), (2, 7), (3, 6), (3, 5), (4, 7), (4, 6), (5, sink), (6, sink), (7, sink). So the minimun number of rounds A can win will be (n - max_flow(from 1 to 8)).

max:

Similarly, link the options that make A win with infinite capacity and just calculate the max flow in that network, So the maximum number of rounds A can win will be max_flow(from 1 to 8).


做法2 (math):

max:

Consider the option A will win : a 1 a_1 a1 -> b 2 b_2 b2, a 2 a_2 a2 -> b 3 b_3 b3, a 3 a_3 a3 -> b 1 b_1 b1,so the answer is : min( a 1 a_1 a1, b 2 b_2 b2) + min( a 2 a_2 a2, b 3 b_3 b3) + min( a 3 a_3 a3, b 1 b_1 b1).

min:

The answer is : m a x ( 0 , a 1 − b 1 − b 3 , a 2 − b 2 − b 1 , a 3 − b 3 − b 2 ) max({0, a_1 - b_1 - b_3, a_2 - b_2 - b_1, a_3 - b_3 - b_2}) max(0,a1b1b3,a2b2b1,a3b3b2).

Proof:

Obviously, this is a lower bound, but can we reach it? Just to prove it :

  1. ( a 1 − b 1 − b 3 a_1-b_1-b_3 a1b1b3) + ( a 2 − b 1 − b 2 a_2 - b_1 - b_2 a2b1b2) + ( a 3 − b 2 − b 3 a_3 - b_2 - b_3 a3b2b3) = − n -n n.
  2. B 1 = a 1 − b 1 − b 3 > = − n B_1 = a_1-b_1-b_3 >= -n B1=a1b1b3>=n
  3. B 2 = a 2 − b 1 − b 2 > = − n B_2=a_2-b_1-b_2 >= -n B2=a2b1b2>=n
  4. B 3 = a 3 − b 2 − b 3 > = − n B_3=a_3-b_2-b_3 >= -n B3=a3b2b3>=n
  5. If two of ( B 1 , B 2 , B 3 B_1,B_2,B_3 B1,B2,B3) are greater than 0, then the other is less than -n, but this is impossible, all three are either less than or equal to 0, or only one is greater than 0. I.If B 1 < = 0 B_1<=0 B1<=0, B 2 < = 0 B_2<=0 B2<=0 and B 3 < = 0 B3<=0 B3<=0,this is correct. II.Only one is greater than 0.For example, a 1 − b 1 − b 3 > 0 a_1-b_1-b_3>0 a1b1b3>0, and after removing the game that Alice won, a 1 = b 1 + b 3 a_1=b_1+b_3 a1=b1+b3, so that b 1 b_1 b1 and b 3 b_3 b3 consume a 1 a_1 a1. At this time, b 1 b_1 b1=0, b 3 b_3 b3=0, a 1 a_1 a1=0, obviously a 2 a_2 a2 , a 3 a_3 a3 can’t win b 2 b_2 b2.

最大流 AC Codes:

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <cstring>

using namespace std;
typedef long long ll;

const int N = 15, INF = 0x3f3f3f3f;
int n;
int g[N][N], pre[N], flow[N], d[N];

int Edmonds_Karp(int s, int t) {
    int max_flow = 0;
    while (1) {
        memset(pre, -1, sizeof pre);
        memset(d, 0x3f, sizeof d);
        flow[s] = INF, d[s] = 0;
        queue<int> Q;
        Q.push(s);
        while (!Q.empty()) {
            int u = Q.front();
            Q.pop();
            if (u == t) break;
            for (int v = 1; v <= 8; v++) {
                if (v != s && g[u][v] > 0 && d[v] == INF) {
                    pre[v] = u, d[v] = d[u] + 1, flow[v] = min(flow[u], g[u][v]);
                    Q.push(v);
                }
            }
        }
        if (d[t] == INF) break;
        max_flow += flow[t];
        int cur = t;
        while (cur != s) {
            int fa = pre[cur];
            g[fa][cur] -= flow[t], g[cur][fa] += flow[t];
            cur = fa;
        }
    }
    return max_flow;
}

int main() {
    cin >> n;
    int a1, a2, a3, b1, b2, b3;
    cin >> a1 >> a2 >> a3 >> b1 >> b2 >> b3;
    g[1][2] = a1, g[1][3] = a2, g[1][4] = a3, g[5][8] = b1, g[6][8] = b2, g[7][8] = b3;
    g[2][5] = g[2][7] = g[3][6] = g[3][5] = g[4][7] = g[4][6] = INF;
    cout <<  n - Edmonds_Karp(1, 8) << ' ';
    memset(g, 0, sizeof g);
    g[1][2] = a1, g[1][3] = a2, g[1][4] = a3, g[5][8] = b1, g[6][8] = b2, g[7][8] = b3;
    g[2][6] = g[3][7] = g[4][5] = INF;
    cout << Edmonds_Karp(1, 8) << '\n';
    return 0;
}

做法2 AC Codes:

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <cstring>

using namespace std;

int main() {
    cin >> n;
    int a1, a2, a3, b1, b2, b3;
    cin >> a1 >> a2 >> a3 >> b1 >> b2 >> b3;
    cout << max({0, a1 - b1 - b3, a2 - b2 - b1, a3 - b3 - b2}) << ' ';
    cout << min(a1, b2) + min(a2, b3) + min(a3, b1) << '\n';
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值