2010-1105

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

题意是有很多堆高度不超过2的石头,石头有两种颜色,A只能拿白色的石头,B只能拿黑色的石头,如果拿的是最底下的石头,那么那整一堆石头都会崩溃掉。轮流取,直到有一个人没法取了,另一个人就赢,要求根据给出的石头的信息(每种石头堆的数量),判断A是否先后手的胜负。
[[BR]]
根据题目的说法,最多只有六种堆(从左到右表示堆的顶部到底部:

{{{
w, b, wb, bw, ww, bb
}}}
实际上一个ww(或一个bb)可以拆分成两个w(或两个b)。而一个w和一个b是可以互相抵消掉的,这样是不影响博弈结果的,一个wb和一个bw也能互相消掉,同样不影响结果。假设经过以上拆分和抵消之后,最后变成有m个w, m个wb,那么在纸上模拟一下博弈过程(B肯定先拿wb中的b,这样会使对方少一个w,A肯定会先拿wb中的w,减少对方的威胁),就可以发现当2m == n时,是先手必败的,而2m > n时,总是A胜,2m < n时,是B必胜。对bw, 和b的情况,也是类似的。
[[BR]]
我的代码:

{{{
#!cpp
#include <cstdio>
#include <cstring>
using namespace std;

int main() {
    int n;
    long long a, w, wb, b, bw;
    char buff[64];
    while (scanf("%d", &n) != EOF) {
        w = wb = 0;
        for (int i = 0; i < n; i++) {
            scanf("%s %lld", buff, &a);
            if (strcmp(buff, "w") == 0) {
                w += a;
            } else if (strcmp(buff, "b") == 0) {
                w -= a;
            } else if (strcmp(buff, "wb") == 0) {
                wb += a;
            } else if (strcmp(buff, "bw") == 0) {
                wb -= a;
            } else if (strcmp(buff, "ww") == 0) {
                w += 2 * a;
            } else {
                w -= 2 * a;
            }
        }
        bool win1, win2;
        if (w >= 0) {
            win1 = w * 2 > wb ? true : false;
            win2 = w * 2 >= wb ? true : false;
        } else {
            b = -w;
            bw = -wb;
            win1 = b * 2 < bw ? true : false;
            win2 = b * 2 <= bw ? true : false;
        }
        printf("%s %s\n", win1 ? "win" : "lose", win2 ? "win" : "lose");
    }
    return 0;
}

}}}

by vout

题意是有很多堆高度不超过2的石头,石头有两种颜色,A只能拿白色的石头,B只能拿黑色的石头,如果拿的是最底下的石头,那么那整一堆石头都会崩溃掉。轮流取,直到有一个人没法取了,另一个人就赢,要求根据给出的石头的信息(每种石头堆的数量),判断A是否先后手的胜负。


根据题目的说法,最多只有六种堆(从左到右表示堆的顶部到底部:

w, b, wb, bw, ww, bb

实际上一个ww(或一个bb)可以拆分成两个w(或两个b)。而一个w和一个b是可以互相抵消掉的,这样是不影响博弈结果的,一个wb和一个bw也能互相消掉,同样不影响结果。假设经过以上拆分和抵消之后,最后变成有m个w, m个wb,那么在纸上模拟一下博弈过程(B肯定先拿wb中的b,这样会使对方少一个w,A肯定会先拿wb中的w,减少对方的威胁),就可以发现当2m == n时,是先手必败的,而2m > n时,总是A胜,2m < n时,是B必胜。对bw, 和b的情况,也是类似的。


我的代码:

#include <cstdio>
#include <cstring>
using namespace std;
int main() {
    int n;
    long long a, w, wb, b, bw;
    char buff[64];
    while (scanf("%d", &n) != EOF) {
        w = wb = 0;
        for (int i = 0; i < n; i++) {
            scanf("%s %lld", buff, &a);
            if (strcmp(buff, "w") == 0) {
                w += a;
            } else if (strcmp(buff, "b") == 0) {
                w -= a;
            } else if (strcmp(buff, "wb") == 0) {
                wb += a;
            } else if (strcmp(buff, "bw") == 0) {
                wb -= a;
            } else if (strcmp(buff, "ww") == 0) {
                w += 2 * a;
            } else {
                w -= 2 * a;
            }
        }
        bool win1, win2;
        if (w >= 0) {
            win1 = w * 2 > wb ? true : false;
            win2 = w * 2 >= wb ? true : false;
        } else {
            b = -w;
            bw = -wb;
            win1 = b * 2 < bw ? true : false;
            win2 = b * 2 <= bw ? true : false;
        }
        printf("%s %s\n", win1 ? "win" : "lose", win2 ? "win" : "lose");
    }
    return 0;
}

by vout