SGU138 Games of Chess

来源:互联网 发布:js 更新url不刷新页面 编辑:程序博客网 时间:2024/05/20 17:41

SGU138 Games of Chess

题目大意

N个人玩擂台赛(胜者留下接受挑战),给出每个人的参赛场次,构造对阵序列及每场的胜负

算法思路

将所有人按照参赛场数排序,然后找出一条尽量靠右的分割线,使得右边的组可以战胜左边
策略为,若第N个人参赛M场,则先让他战胜左边M - 1次,再输给第N - 1个人,以此类推
但是最后第K个人战胜左边所有人后,可能还有剩余的参赛场次,设为P
可以在开始前,让第K个人先输给第N个人P / 2场,再按上述方案构造即可

时间复杂度: O(NlogN)

代码

/** * Copyright © 2015 Authors. All rights reserved. *  * FileName: 138.cpp * Author: Beiyu Li <sysulby@gmail.com> * Date: 2015-06-15 */#include <bits/stdc++.h>using namespace std;#define rep(i,n) for (int i = 0; i < (n); ++i)#define For(i,s,t) for (int i = (s); i <= (t); ++i)#define foreach(i,c) for (__typeof(c.begin()) i = c.begin(); i != c.end(); ++i)typedef long long LL;typedef pair<int, int> Pii;const int inf = 0x3f3f3f3f;const LL infLL = 0x3f3f3f3f3f3f3f3fLL;const int maxn = 100 + 5;int n;Pii a[maxn];int pre[maxn];int main(){        scanf("%d", &n);        For(i,1,n) scanf("%d", &a[i].first), a[i].second = i;        sort(a + 1, a + n + 1);        For(i,1,n) pre[i] = pre[i-1] + a[i].first;        int now = 0;        for (int i = n; i >= 1; --i) {                now += a[i].first - (i < n? 2: 0);                if (now >= pre[i-1]) {                        int c = (now - pre[i-1]) / 2;                        a[0] = Pii(c, a[i].second);                        a[i].first -= c;                        break;                }        }        printf("%d\n", pre[n] / 2);        int l = 0, r = n;        rep(i,pre[n]/2) {                if (!--a[r].first) {                        printf("%d %d\n", a[r-1].second, a[r].second);                        --a[--r].first;                } else {                        if (!a[l].first) ++l;                        printf("%d %d\n", a[r].second, a[l].second);                        --a[l].first;                }        }        return 0;}

0 0
原创粉丝点击