hrbust 1976 Back (2013年校赛 二分图+博弈)

本文介绍了一款名为“Back”的博弈论游戏,该游戏基于围棋盘面进行,玩家需按照特定规则回取棋子。文章详细解释了游戏规则,并提供了一个算法解决方案来预测玩家是否能够获胜。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Back
Time Limit: 2000 MSMemory Limit: 65536 K
Total Submit: 7(2 users)Total Accepted: 1(1 users)Rating: Special Judge: No
Description

"Go" is a board game for two players that originated inChina more than 2,500 years ago. The game is noted for being rich in strategy despite its relatively simple rules.

Xiaodao && xiaodai were playing "Go", but xiaodao always lose, so she came up with a brand new game on the board so called "Back".

The stones are already on the board at the beginning. The two players alternately take back the stones. The first player can take back any stone on the board, and from the second turn, the player can only take back the stone which are 4-adjacent with the previous one. Xiaodao moves first. The player who can not take back any stone under this rule will be lose.

Of couse, xiaodao want to predict weather she could win or not, no matter what decisions the opponent going to take. We assume both player will play optimally.

Input

The first line contains the number of test casesT(1 ≤ T ≤ 100), then each case contain one line two numbern, m — the size of the board(1 ≤ n, m ≤ 32).

The nextn lines, each line contains m characters "."(empty) or "x"(stone) — the corresponding board at the beginning of the game.

Output

For each of the test cases numbered in order from 1 to T, output "Case #", followed by the case number, followed by ": " and a "Yes"(win) or "No"(lose).

Sample Input
3
1 1
.
3 3
.x.
xxx
.x.
4 5
.xx..
.x.xx
.xx.x
xxx.x

Sample Output
Case #1: No
Case #2: Yes
Case #3: No

Source
"科林明伦杯"哈尔滨理工大学第三届ACM程序设计团队赛
Author
xiaodao

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define clr(x) memset(x,0,sizeof(x))
struct node{
    int to,next;
}qq[50*50*50*50];
int head[50*50*50];
int tot;
void add(int s,int u)
{
    qq[tot].to=u;
    qq[tot].next=head[s];
    head[s]=tot++;
}
int l[50*50*50];
int v[50*50*50];
int find(int x){
    int k,i;
    for(i=head[x];i;i=qq[i].next){
        k=qq[i].to;
        if(!v[k]){
            v[k]=1;
            if(l[k]==0||find(l[k])){
                l[k]=x;
                return 1;
            }
        }
    }
    return 0;
}
char map[50][50];
int vis[50][50];
int num[50][50];
int p,q;
int ok(int x,int y){
    if(x>=0&&x<p&&y>=0&&y<q)return 1;
    return 0;
}
struct node1{
    int x,y;
}t,tt;
int main(){
    int T,i,j,ca=1;
    scanf("%d",&T);
    queue<struct node1>que;
    while(T--){
        int flag=0;
        scanf("%d%d",&p,&q);
        clr(map);
        clr(vis);
        for(i=0;i<p;i++){
            scanf("%s",&map[i]);
        }
        int tmp=1;
        for(i=0;i<p;i++){
            for(j=0;j<q;j++)
                num[i][j]=tmp++;
        }
        int fff=0;
        for(i=0;i<p;i++){
            for(j=0;j<q;j++){
                if(!que.empty())que.pop();
                if(map[i][j]=='x'&&!vis[i][j]){

                  fff++;
                    clr(head);
                    clr(l);
                    tot=1;
                    vis[i][j]=1;
                    t.x=i;t.y=j;
                    que.push(t);
                    int res=1;
                    while(!que.empty()){
                        tt=que.front();
                        que.pop();
                        if(ok(tt.x+1,tt.y)&&map[tt.x+1][tt.y]=='x'){
                            add(num[tt.x][tt.y],num[tt.x+1][tt.y]);
                            add(num[tt.x+1][tt.y],num[tt.x][tt.y]);
                            if(!vis[tt.x+1][tt.y]){
                                res++;vis[tt.x+1][tt.y]=1;t.x=tt.x+1;t.y=tt.y;que.push(t);
                            }
                        }
                        if(ok(tt.x-1,tt.y)&&map[tt.x-1][tt.y]=='x'){
                            add(num[tt.x-1][tt.y],num[tt.x][tt.y]);
                            add(num[tt.x][tt.y],num[tt.x-1][tt.y]);
                            if(!vis[tt.x-1][tt.y]){
                                res++;vis[tt.x-1][tt.y]=1;t.x=tt.x-1;t.y=tt.y;que.push(t);
                            }

                        }
                        if(ok(tt.x,tt.y+1)&&map[tt.x][tt.y+1]=='x'){
                            add(num[tt.x][tt.y],num[tt.x][tt.y+1]);
                            add(num[tt.x][tt.y+1],num[tt.x][tt.y]);
                            if(!vis[tt.x][tt.y+1]){
                                res++;vis[tt.x][tt.y+1]=1;t.x=tt.x;t.y=tt.y+1;que.push(t);
                            }
                        }
                        if(ok(tt.x,tt.y-1)&&map[tt.x][tt.y-1]=='x'){
                            add(num[tt.x][tt.y],num[tt.x][tt.y-1]);
                            add(num[tt.x][tt.y-1],num[tt.x][tt.y]);
                            if(!vis[tt.x][tt.y-1]){
                                 res++;vis[tt.x][tt.y-1]=1;t.x=tt.x;t.y=tt.y-1;que.push(t);
                            }
                        }

                    }
                     int sum=0;
                        int n=num[p-1][q-1];
                        for(int k=1;k<=n;k++){
                            clr(v);
                            if(find(k))sum++;
                        }

                        if(sum!=res){flag=1;goto loop;}
                }
            }
        }
    loop:    if(!flag||fff==0)printf("Case #%d: No\n",ca++);
            else printf("Case #%d: Yes\n",ca++);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值