2014-02-17 16:47:35Morris

[UVA][博弈] 11818 - Mouse & a Cheese

Problem A

Game – Mouse and Cheese
Input: Standard Input

Output: Standard Output


SOHA and TARA have recently invented a new game called “Mouse and Cheese”. As the name suggests, this game involves a mouse searching for a piece of cheese. The game is played on a 3x3 board as shown in the diagram below. Each cell is uniquely numbered with an integer between 1 and 9. The board contains 12 sticks (the blue lines in the diagram).

 

 

 

 

 

 

 

 

 

 

 

 

 

Initially a mouse and a piece of cheese are placed on two different cells. In the example to the right, the mouse is placed on ‘cell 8’ and the cheese is placed on ‘cell 3’.

The rule of the game goes like this: It’s a two-player game where the players make moves alternately. SOHA, being player 1, goes first. In each move, the player selects a stick and throws it away. After each move, if the mouse can reach the cell containing the cheese without touching any of the remaining sticks, then that player is declared as the winner? If both play perfectly, who wins?

 

Before the game starts, some of the sticks are removed. You will be given the coordinates of these sticks and the cell numbers of the mouse and cheese. A stick is represented using the coordinates of its end points. The lower left of the grid is the origin (0, 0). The two sticks surrounding the cheese, in the example above, has coordinates “2 0 2 1” and “2 1 3 1”.  Note that the end-points of a stick can be given in any order. That is “2 0 2 1” could be given as “2 1 2 0”.

 

Input

The first line of input is an integer T(T<1000) that determines the number of test cases. Each case starts with 3 integers S, C and R. S and C denotes the location of the mouse and cheese respectively. Each of the next R lines contains 4 space-separated integers that give the coordinates of the sticks removed from the board before the start of the game.

Notes and Constraints
1 <= S,C <= 9
S != C
0 <= R <= 12

For each case, all the removed sticks will be distinct.

 

Output

For each case, output the case number first, starting with 1, followed by the name of the player who wins. If the mouse can already reach the cheese before the game starts, output “No Cheese!” instead. Look at the samples for exact format.

 

Sample Input

Output for Sample Input

3

1 2 1

1 1 1 0

1 4 0

7 2 2

1 2 1 3

2 2 2 3

Case 1: No Cheese!

Case 2: SOHA

Case 3: TARA

 


Problemsetter: Sohel Hafiz

Special Thanks: Arifuzzaman Arif

題目描述:// zerojudge 已經有中文版,在此略過

題目解法:

博弈問題,但是數據處理上有點麻煩,這裡採用最典型的打表方式。

// (起點座標, 終點座標, 相鄰格子1, 格子1禁用方向
, 相鄰格子2, 格子2禁用方向)


#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;

struct stick {
    int sx, sy, ex, ey;
    int n1, d1, n2, d2;
} D[12] = {
    {1, 1, 1, 0, 1, 3, 2, 2},
    {2, 1, 2, 0, 2, 3, 3, 2},
    {0, 1, 1, 1, 1, 0, 4, 1},
    {1, 1, 2, 1, 2, 0, 5, 1},
    {2, 1, 3, 1, 3, 0, 6, 1},
    {1, 2, 1, 1, 4, 3, 5, 2},
    {2, 2, 2, 1, 5, 3, 6, 2},
    {0, 2, 1, 2, 4, 0, 7, 1},
    {1, 2, 2, 2, 5, 0, 8, 1},
    {2, 2, 3, 2, 6, 0, 9, 1},
    {1, 3, 1, 2, 7, 3, 8, 2},
    {2, 3, 2, 2, 8, 3, 9, 2}};
// up 0, down 1, left 2, right 3
int bfs(int S, int C, int mask) {
    int dx[] = {-1, 1, 0, 0};
    int dy[] = {0, 0, -1, 1};
    S--, C--;
    int sx = 2 - S/3, sy = S%3;
    int ex = 2 - C/3, ey = C%3;
    int i, j, k, x, y;
    int ban[3][3][4] = {}, used[3][3] = {};
    for(i = 0; i < 12; i++) {
        if((mask>>i)&1) {
            j = D[i].n1 - 1;
            x = 2 - j/3, y = j%3;
            ban[x][y][D[i].d1] = 1;
            j = D[i].n2 - 1;
            x = 2 - j/3, y = j%3;
            ban[x][y][D[i].d2] = 1;
        }
    }
    queue<int> X, Y;
    X.push(sx), Y.push(sy);
    while(!X.empty()) {
        x = X.front(), y = Y.front();
        X.pop(), Y.pop();
        if(x == ex && y == ey)
            return 1;
        for(i = 0; i < 4; i++) {
            if(ban[x][y][i])    continue;
            sx = x + dx[i], sy = y + dy[i];
            if(sx < 0 || sy < 0 || sx >= 3 || sy >= 3)
                continue;
            if(used[sx][sy] == 0) {
                used[sx][sy] = 1;
                X.push(sx), Y.push(sy);
            }
        }
    }
    return 0;            
}
int used[1<<12], dp[1<<12];
int dfs(int S, int C, int mask) {
    if(used[mask])    return dp[mask];
    used[mask] = 1;
    int &ret = dp[mask];
    ret = 0;
    if(bfs(S, C, mask)) {
        used[mask] = 1, ret = 0;
        return ret;
    }
    for(int i = 0; i < 12; i++) {
        if((mask>>i)&1)
            ret |= !(dfs(S, C, mask^(1<<i)));
    }
    return ret;
}
int main() {
    int testcase, cases = 0;
    int S, C, R;
    int i, j, k;
    scanf("%d", &testcase);
    while(testcase--) {
        scanf("%d %d %d", &S, &C, &R);
        int mask = (1<<12) - 1;
        for(i = 0; i < R; i++) {
            int sx, sy, ex, ey;
            scanf("%d %d %d %d", &sx, &sy, &ex, &ey);
            for(j = 0; j < 12; j++) {
                if(D[j].sx == sx && D[j].sy == sy &&
                    D[j].ex == ex && D[j].ey == ey)
                    mask ^= 1<<j;
                if(D[j].sx == ex && D[j].sy == ey &&
                    D[j].ex == sx && D[j].ey == sy)
                    mask ^= 1<<j;
            }
        }
        printf("Case %d: ", ++cases);
        if(bfs(S, C, mask))
            puts("No Cheese!");
        else {
            memset(used, 0, sizeof(used));
            puts(dfs(S, C, mask) ? "SOHA" : "TARA");
        }
    }
    return 0;
}