BZOJ1443: [JSOI2009]游戏Game

Description

Input

输入数据首先输入两个整数N,M,表示了迷宫的边长。 接下来N行,每行M个字符,描述了迷宫。

Output

若小AA能够赢得游戏,则输出一行"WIN",然后输出所有可以赢得游戏的起始位置,按行优先顺序输出 每行一个,否则输出一行"LOSE"(不包含引号)。

Sample Input

3 3
.##
...
#.#

Sample Output

WIN
2 3
3 2

HINT

对于100%的数据,有1≤n,m≤100。 对于30%的数据,有1≤n,m≤5。

题目传送门

这道题挺好,想我半天。。

首先看到这个图就想跑网络流,给他一套黑白染色操作,mengbier No.1

根据题意其实放棋子就是放障碍,如果它四周有联通块最大匹配不完美就GG

但是按这个复杂度跑会GG,mengbier No.2

继而想更优的方法,画个图跑一跑。。。

发现其实不用这么麻烦??

这是二分图匹配啊,如果你当前这个棋子可以不在完美匹配里跑就没问题啊??
有点不会表达看图吧:

像2号点,是不必要在这个二分图里面的,你放一个棋子,那么对手往哪边跑你都可以跑他的匹配,所以赢

但是如果在1点,就只能沿着边一直跑到死???然后就会爆炸

然后WIN要大写差评~~~ mengbier No.3

为什么这道题怎么水还要写这么多。。。

友情支援一组小数据:

/*
Sample Int
5 5
.....
.....
.....
.....
...#.

Sample Output
WIN
1 1
1 3
1 5
2 2
2 4
3 1
3 3
3 5
4 2
4 4
5 1
5 3
5 5

*/

代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct node{
    int x,y,next;
}a[210000];int len,last[210000];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
const int dx[4]={1,0,-1,0};
const int dy[4]={0,1,0,-1};
struct form{
    int x,y;
}p[110000],ans[110000];
int n,m;
int col[110][110];
int ys[110][110],id;
char st[110];
bool in[11000];
int match[11000];
int tim,chw[11000];
bool findmuniu(int x)
{
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(chw[y]!=tim)
        {
            chw[y]=tim;
            if(match[y]==0||findmuniu(match[y])==true)
            {
                in[y]=true;
                match[y]=x,match[x]=y;
                return true;
            }
        }
    }
    return false;
}
bool findanother(int x)
{
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(chw[y]!=tim&&y!=match[x])
        {
            chw[y]=tim;
            if(match[y]==0||findanother(match[y])==true)
                return true; 
        }
    }
    return false;
}
/*
Sample Int
5 5
.....
.....
.....
.....
...#.

Sample Output
WIN
1 1
1 3
1 5
2 2
2 4
3 1
3 3
3 5
4 2
4 4
5 1
5 3
5 5

*/
bool cmp(form a,form b){if(a.x==b.x)return a.y<b.y;return a.x<b.x;}
int main()
{
    scanf("%d%d",&n,&m);id=0;
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            col[i][j]=1;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",st+1);
        for(int j=1;j<=m;j++)
        {
            if(st[j]=='.')ys[i][j]=++id,p[id].x=i,p[id].y=j;
            if(j==1)col[i][j]^=col[i-1][j];
            else col[i][j]^=col[i][j-1];
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(ys[i][j]!=0&&col[i][j]%2==0)
                for(int k=0;k<4;k++)
                    if(ys[i+dx[k]][j+dy[k]]!=0)
                        ins(ys[i][j],ys[i+dx[k]][j+dy[k]]),ins(ys[i+dx[k]][j+dy[k]],ys[i][j]);
    tim=0;
    memset(match,0,sizeof(match));
    memset(chw,0,sizeof(chw));
    memset(in,false,sizeof(in));
    for(int i=1;i<=id;i++)
    {
        if(col[p[i].x][p[i].y]==1)continue;
        tim++;
        if(findmuniu(i)==true)in[i]=true;
    }
    int tot=0;
    for(int i=1;i<=id;i++)
    {
        if(in[i]==false)ans[++tot]=p[i];
        else
        {
            tim++;
            if(findanother(match[i])==true)ans[++tot]=p[i];
        }
    }
    if(tot==0)printf("LOSE\n");
    else 
    {
        printf("WIN\n");
        sort(ans+1,ans+1+tot,cmp);
        for(int i=1;i<tot;i++)printf("%d %d\n",ans[i].x,ans[i].y);
        printf("%d %d",ans[tot].x,ans[tot].y);
    }
    return 0;
}

by_lmy

猜你喜欢

转载自www.cnblogs.com/MT-LI/p/8909240.html