[JSOI2009]游戏

题目描述

小AA和小YY得到了《喜羊羊和灰太狼》的电影票,都很想去观看,但是电影票只有一张,于是他们用智力游戏决定胜负,赢得游戏的人可以获得电影票。在N*M的迷宫中有一个棋子,小AA首先任意选择棋子放置的位置。然后,小YY和小AA轮流将棋子移动到相邻的格子里。游戏的规则规定,在一次游戏中,同一个格子不能进入两次,且不能将棋子移动到某些格子中去。当玩家无法继续移动棋子时,游戏结束,最后一个移动棋子的玩家赢得了游戏。例如下图所示的迷宫,迷宫中”.”表示棋子可以经过的格子,而”#”表示棋子不可以经过的格子:

                             .##
                             ...
                             #.# 

若小AA将棋子放置在(1,1),则小 AA 则无论如何都无法赢得游戏。
而若小AA将棋子放置在(3,2)或(2,3),则小AA能够赢得游戏。例如,小AA将棋子放置在(3,2),小YY只能将它移动到(2,2),此时小AA再将棋子移动到(2,3),就赢得了游戏。

小AA和小YY都是绝顶聪明的小朋友,且从不失误。小AA到底能不能赢得这场游戏,从而得到珍贵的电影票呢?
输入输出格式
输入格式:
输入数据首先输入两个整数 N,M,表示了迷宫的边长。接下来 N 行,每行 M 个字符,描述了迷宫。
输出格式:
若小 AA 能够赢得游戏,则输出一行”WIN”,然后输出所有可以赢得游戏的起始位置,按行优先顺序输出,每行一个。否则输出一行”LOSE”(不包含引号)。
输入输出样例
输入样例#1:
3 3
.##

#.#
输出样例#1:
WIN
2 3
3 2
说明
对30%的数据,有1<=n,m<=5,对100%的数据,有1<=n,m<=100.

分析

这道题要是没有不可到的地方,就和这道题一样了,然而,它有阻挡,所以自然想到二分图匹配,对于先手而言,若二分图不存在完美匹配,则放在非匹配点一定是最优的。因为后手的第一步必定走到一个匹配点,先手只需要保证一直沿着匹配边走即可,因为不可能存在非匹配边、匹配边交叉出现的增广路,即先手总是能比后手多走一步(根据最大匹配的定义),若二分图存在完美匹配,那么先手无论如何放置都会输,具体同理,那么先判断是否是完美匹配,若是这道题也就完了,不是的话找到非匹配点就行了,时间:4500ms。
上代码

#include<bits/stdc++.h>
using namespace std;
int next[200001],head[200001],now=0,point[200001],match[200001],x[200001],y[200001],mat[200001],dx[5]={0,0,0,1,-1},dy[5]={0,1,-1,0,0};
bool visit[200001],mark[200001];
char ch[200][200];
void add(int x,int y){ next[++now]=head[x],head[x]=now,point[now]=y;}
bool dfs(int k){
    for(int i=head[k],u;i;i=next[i])
        if(!visit[u=point[i]]){
            visit[u]=1;
            if(dfs(match[u])||match[u]==-1){
                match[u]=k;
                mat[k]=u;
                return true;
            }
        }
    return false;
}
int main(){
    int n,m,u=0,v=0,flag=0,fi=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%s",ch[i]+1);
    for(int i=1;i<=n;i++){
        fi^=1;
        for(int j=fi+1;j<=m;j+=2) if(ch[i][j]=='.'){
                x[++u]=i*m+j;
                for(int k=1;k<=4;k++){
                    int xx=i+dx[k],yy=j+dy[k];
                    if(ch[xx][yy]=='.') add(i*m+j,xx*m+yy),add(xx*m+yy,i*m+j);
                }
            }
    }
    fi=1;
    for(int i=1;i<=n;i++){
        fi^=1;
        for(int j=fi+1;j<=m;j+=2) if(ch[i][j]=='.') y[++v]=i*m+j;
    }
    memset(match,-1,sizeof(match));
    for(int i=1;i<=u;i++){
        memset(visit,0,sizeof(visit));
        if(!dfs(x[i])) flag=1,mark[x[i]]=1;
    }
    for(int i=1;i<=v;i++){
        if(match[y[i]]==-1) mark[y[i]]=1,flag=1;
        else{
            memset(visit,0,sizeof(visit));
            visit[y[i]]=1;
            if(dfs(match[y[i]])) match[y[i]]=-1,mark[y[i]]=1,flag=1;
        }
    }
    for(int i=1;i<=v;i++){
        memset(visit,0,sizeof(visit));
        if(!dfs(y[i])) flag=1,mark[y[i]]=1;
    }
    for(int i=1;i<=u;i++){
        if(match[x[i]]==-1) mark[x[i]]=1,flag=1;
        else{
            memset(visit,0,sizeof(visit));
            visit[x[i]]=1;
            if(dfs(match[x[i]])) match[x[i]]=-1,mark[x[i]]=1,flag=1;
        }
    }
    if(!flag){
        printf("LOSE\n");
        return 0;
    }
    printf("WIN\n");
    for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(mark[i*m+j]) printf("%d %d\n",i,j);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sjzezwzy/article/details/80884303
今日推荐