zoukankan      html  css  js  c++  java
  • 2019.01.03-bzoj-1443-[JSOI2009]游戏Game

    题目描述:

    算法标签:博弈,二分图匹配

    思路:

    二分图匹配每次是从一条匹配边走向非匹配边,对应到这题的博弈中,倘若先手在某一点上,后手走匹配边,达到另一点,先手在走一条非匹配边,表示恰好势均力敌的状态。此时倘若先手走一点匹配不到其他点,则这个点作为起点必然可以导致后手胜利。考虑一下还有没有其他情况,从这些点反向往回走,每次间隔走的那些点,最后也会剩余一个点没有匹配点所以也是答案。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=105,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};char s[N][N];
    int n,m,d[N][N],now,px[N][N],py[N][N];bool pd,v[N][N],ed[N][N];
    il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;}
    il bool dfs(int x,int y){
        d[x][y]=now;
        if(px[x][y]&&d[px[x][y]][py[x][y]]!=now)return dfs(px[x][y],py[x][y]);
        for(int i=0;i<4;i++){
            int xx=x+dx[i],yy=y+dy[i];
            if(!px[xx][yy]&&s[xx][yy]=='.'&&d[xx][yy]!=now){
                px[xx][yy]=x;py[xx][yy]=y;
                px[x][y]=xx;py[x][y]=yy;return 1;
            }
        }
        for(int i=0;i<4;i++){
            int xx=x+dx[i],yy=y+dy[i];
            if(s[xx][yy]=='.'&&d[xx][yy]!=now&&dfs(xx,yy)){
                px[xx][yy]=x;py[xx][yy]=y;
                px[x][y]=xx;py[x][y]=yy;return 1;
            }
        }
        return 0;
    }
    il void dfs2(int x,int y){
        if(ed[x][y])return;v[x][y]=1;ed[x][y]=1;
        for(int i=0;i<4;i++){
            int xx=dx[i]+x,yy=dy[i]+y;
            if(s[xx][yy]=='.'&&px[xx][yy])dfs2(px[xx][yy],py[xx][yy]);
        }
    }
    int main()
    {
        n=read();m=read();
        for(int i=1;i<=n;i++)scanf(" %s",s[i]+1);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(s[i][j]=='.'&&!px[i][j])now++,dfs(i,j);
            }
        }
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
            if(!px[i][j]&&s[i][j]=='.')v[i][j]=1;
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
            if(!px[i][j]&&s[i][j]=='.')dfs2(i,j);
        int ans=0;
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
            if(v[i][j])ans++;
        printf("%d
    ",ans);
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
            if(v[i][j])printf("%d %d
    ",i,j);
        return 0;
    }
    View Code
  • 相关阅读:
    重学《C#高级编程》(序)
    分布式锁-基于redis的分布式锁实现
    CentOS 7.9 安装docker
    JAVA使用UDP收发文件
    MYSQL 查询指定范围内的经纬度
    tomcat 8.x 配置 HTTPS 协议
    JDBC 连接 Oracle 11g 集群
    [centos7] svn
    单例模式
    Extjs 中 Treepanel 实现级联选中效果
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10217831.html
Copyright © 2011-2022 走看看