myzee的解题报告

纯粹为了兴趣去搞算法,为了赢冠军而忍受长期的默默无闻 www.myzee.cn

uva 12530 Game of Tiles (二分图完美匹配+博弈论)

题目链接:   uva 12530

题目大意:   给出50x50的地图,地图上某些点不能走,可以走四个方向

                  Alice选任意一个点开始,然后和Bob轮流走,重复的点不能走

                  最后轮到谁走却不能移动棋子就输

解题思路:   二分图的完美匹配:最大匹配数刚好覆盖完左右集合的顶点

                  若图存在完美匹配,先手选择任意点,后手都选择与其匹配的点,先手必输

                  若图不存在完美匹配,先手选择不属于最大匹配的点,先手必胜

                  找出所有的连通块,进行黑白染色,即选择某点染黑,周围点染白

                  判断是否有一个块不存在完美匹配的,若存在先手选它则必胜

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 53
char Map[MAX][MAX];
int Co[MAX][MAX],F[MAX][MAX],n,m,an;
int cx[MAX*MAX],cy[MAX*MAX],visit[MAX*MAX],Index;
int Fx[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
struct snode{
    int x,y;
}ans[MAX*MAX];

struct node{
    int to,next;
}Edge[100000];

int pre[MAX*MAX];

void Add_edge(int a,int b)
{
    Edge[Index].to=b;
    Edge[Index].next=pre[a];
    pre[a]=Index++;
}

void Color(int x,int y,int k)  //不同的连通块黑白染色
{
    int i,xx,yy;
    Map[x][y]='X';
    Co[x][y]=k;
    ans[an].x=x,ans[an++].y=y;
    F[x][y]=an;
    for(i=0;i<4;i++)
    {
        xx=Fx[i][0]+x;
        yy=Fx[i][1]+y;
        if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&Map[xx][yy]=='.')
            Color(xx,yy,-k);
    }
}

int DFS(int u,int an)   //匈牙利最大匹配
{
    int i,v;
    for(i=pre[u];i!=-1;i=Edge[i].next)
    {
        v=Edge[i].to;
        if(!visit[v])
        {
            visit[v]=1;
            if(!cy[v]||DFS(cy[v],an))
            {
                cx[u]=v;
                cy[v]=u;
                return 1;
            }
        }
    }
    return 0;
}

int Solve()
{
    int i1,j1,x,y,xx,yy,t;
    Index=0;                      //***
    memset(pre,-1,sizeof(pre));
    for(i1=0;i1<an;i1++)
    {
        x=ans[i1].x;
        y=ans[i1].y;
        t=Co[x][y];
        for(j1=0;j1<4;j1++)
        {
            xx=Fx[j1][0]+x;
            yy=Fx[j1][1]+y;
            if(xx>=1&&xx<=n&&yy>=1&&yy<=m&&Co[xx][yy]==-t)
            {
                Add_edge(F[x][y],F[xx][yy]);           //***
                Add_edge(F[xx][yy],F[x][y]);           //***
            }
        }
    }
    memset(cx,0,sizeof(cx));
    memset(cy,0,sizeof(cy));
    for(i1=1,t=0;i1<=an;i1++)
    {
        if(!cx[i1])               //x匹配y
        {
            memset(visit,0,sizeof(visit));
            t+=DFS(i1,an);        //增广轨
        }
    }
    if(t==an)  //当t==an时候,存在完美匹配
        return 0;
    return 1;
}

int main()
{
    int i,j,k,pd;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        gets(Map[1]+1);
        memset(F,0,sizeof(F));
        memset(Map,'X',sizeof(Map));
        memset(Co,0,sizeof(Co));
        for(i=1;i<=n;i++)
            gets(Map[i]+1);
        k=0; pd=0;
        for(i=1;i<=n&&!pd;i++)
        {
            for(j=1;j<=m&&!pd;j++)
            {
                if(Map[i][j]=='.')
                {
                    an=0; ++k;   //
                    Color(i,j,k);
                    pd=Solve();
                }
            }
        }
        if(pd==1)
            printf("1\n");
        else
            printf("2\n");
    }
    return 0;
}


阅读更多
文章标签: uva
个人分类: UVA 二分图
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭