gcj d题 Fashion Show 二分匹配

来源:互联网 发布:sql query language 编辑:程序博客网 时间:2024/06/09 23:58
题目大意
给定N*N的棋盘和一些士兵,士兵有三种分别为'x','+','o',如果没有士兵则用'.'表示。一个格子最多放置一个士兵,并满足以下要求
1、任意两个在同一条横线或者竖线上的士兵中必须有一个'+'
2、任意两个在同一条斜线上的士兵中必须有一个'x'


现在可以进行的操作是:
1、将已存在的士兵'x'或者'+'升级为'o'
2、将任意一种士兵放在空格子上

问最佳操作,最大化棋盘的分数,棋盘的分数是'x'的数量加'+'的数量加'o'的两倍数量


一个'o'可以表示为一个'+'和一个'x'叠加在一起,所以原问题被拆成了两个子问题:

1、在一个棋盘中最多放置多少个'+',满足约束,每一个斜线中最多只有一个“+‘

2、在一个棋盘中最多放置多少个'x',满足约束,每行每列中最多只有一个'x'

上述两个问题都可以转化为二分匹配问题,对于第二个,左面的点是横坐标x,右面的点是纵坐标y,连接x和y当且仅当x,y这两条直线上没有'x'

同理对于第一个问题,x+y确定一条右上的斜线,x-y确定一条右下的直线,与第一个问题类似建边方式。


代码来自通神orz。。

#include <bits/stdc++.h>using namespace std;const int MAXN = 410;const int MAXM = 20010;const int INF = 1e9;vector<int> G[MAXN];int cx[MAXN], cy[MAXN];int dx[MAXN], dy[MAXN];bool mark[MAXN];int N;int searchPath() {    memset(dx, -1, sizeof(dx));    memset(dy, -1, sizeof(dy));    queue<int> Q;    for (int i = 1; i <= N; i++) if (cx[i] == -1) {        dx[i] = 0;        Q.push(i);    }    int dist = INF;    while (!Q.empty()) {        int u = Q.front(); Q.pop();        if (dx[u] > dist) break;        for (int i = 0; i < (int)G[u].size(); i++) {              int v = G[u][i];              if (dy[v] == -1) {                dy[v] = dx[u] + 1;                if (cy[v] == -1) {                    dist = dy[v];                } else {                    dx[cy[v]] = dy[v] + 1;                    Q.push(cy[v]);                }            }        }    }    return dist != INF;}int findPath(int u) {    for (int i = 0; i < (int)G[u].size(); i++) {        int v = G[u][i];        if (!mark[v] && dy[v] == dx[u] + 1) {            mark[v] = true;            if (cy[v] == -1 || findPath(cy[v])) {                cy[v] = u;                cx[u] = v;                return 1;            }        }    }    return 0;}int MaxMatch() {    int res = 0;    memset(cx, -1, sizeof(cx));    memset(cy, -1, sizeof(cy));    while (searchPath()) {        memset(mark, false, sizeof(mark));        for (int i = 1; i <= N; i++) {            if (cx[i] == -1) {                res += findPath(i);            }        }    }    return res;}// = =============== main function ===========================char a[110][110], b[110][110];bool hasxx[MAXN], hasxy[MAXN];bool haspx[MAXN], haspy[MAXN];int main(void) {    int T;    cin >> T;    for (int t = 1; t <= T; ++ t) {        int n, m;        cin >> n >> m;        for (int i = 1; i <= n; ++ i) for (int j = 1; j <= n; ++ j) {            a[i][j] = b[i][j] = '.';        }        memset(hasxx, false, sizeof(hasxx));        memset(hasxy, false, sizeof(hasxy));        memset(haspx, false, sizeof(haspx));        memset(haspy, false, sizeof(haspy));        for (int i = 0; i < m; ++ i) {            char ch; int x, y;            cin >> ch >> x >> y;            a[x][y] = b[x][y] = ch;            if (ch == 'x') {                hasxx[x] = hasxy[y] = true;            } else if (ch == '+') {                haspx[x - y + n] = haspy[x + y + n + n] = true;            } else {                hasxx[x] = hasxy[y] = true;                haspx[x - y + n] = haspy[x + y + n + n] = true;            }        }        N = n * 4;        for (int i = 1; i <= N; ++ i) G[i].clear();        for (int i = 1; i <= n; ++ i) {            for (int j = 1; j <= n; ++ j) if (b[i][j] == '.' or b[i][j] == '+') {                if (hasxx[i] or hasxy[j]) continue;                G[i].emplace_back(j + n);                //G[j + n].emplace_back(i);            }        }        int tmp1 = MaxMatch();        //cerr << "tmp1: " << tmp1 << endl;        for (int i = 1; i <= n; ++ i) if (cx[i] != -1) {            int j = cx[i] - n;            if (b[i][j] == '.')                b[i][j] = 'x';            else                b[i][j] = 'o';        }        N = 4 * n;        for (int i = 1; i <= N; ++ i) G[i].clear();        for (int i = 1; i <= n; ++ i) {            for (int j = 1; j <= n; ++ j) if (b[i][j] == '.' or b[i][j] == 'x') {                int x = i - j + n;                int y = i + j + n + n;                if (haspx[x] or haspy[y]) continue;                G[x].emplace_back(y);                //G[y].emplace_back(x);            }        }        int tmp2 = MaxMatch();        //cerr << "tmp2: " << tmp2 << endl;        for (int k = 1; k <= n + n; ++ k) {            if (cx[k] != -1) {                int i = (k + cx[k] - n * 3) / 2;                int j = (cx[k] - n - k) / 2;                if (b[i][j] == '.') b[i][j] = '+';                else if (b[i][j] == 'x') b[i][j] = 'o';            }        }        int ans = 0, cnt = 0;        for (int i = 1; i <= n; ++ i) for (int j = 1; j <= n; ++ j) {            if (b[i][j] == 'o') ans += 2;            else if (b[i][j] != '.') ans += 1;            if (a[i][j] != b[i][j]) ++ cnt;        }        cout << "Case #" << t << ": " << ans << ' ' << cnt << endl;        for (int i = 1; i <= n; ++ i) for (int j = 1; j <= n; ++ j) {            if (a[i][j] != b[i][j]) {                cout << b[i][j] << ' ' << i << ' ' << j << endl;            }        }    }    return 0;}


0 0
原创粉丝点击