zoukankan      html  css  js  c++  java
  • BZOJ 1443 [JSOI2009]游戏Game ——博弈论

    好题。

    首先看到棋盘,先黑白染色。

    然后就是二分图的经典模型。

    考虑最特殊的情况,完美匹配,那么先手必胜,

    因为无论如何,先手走匹配边,后手无论走哪条边,总有对应的匹配边。

    如果在不在最大匹配中出发,先手无论如何会走到最大匹配中,然后后手顺着匹配走,一定能胜利。

    (万一又走到非最大匹配中呢,显然这样我们会找到一条增广路,与最大匹配不符)。

    但是最大匹配不止又一种,所以我们需要判断是否在最大匹配中,需要寻找交错路。

    如果在最大匹配中出发,显然先手必胜,(如果走到非最大匹配的点上,那么就相当于找到一条交错路可以替换,反而让非最大匹配换到了最大匹配中)

    然后就相当于求一定不在最大匹配中的点了。

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
     
    #define F(i,j,k) for (int i=j;i<=k;++i)
    #define D(i,j,k) for (int i=j;i>=k;--i)
     
    int mov[4][2]={{0,1},{1,0},{-1,0},{0,-1}};
    vector <int> v[10005];
    int id[105][105],a[105][105],n,m,cnt,vis[10005],linker[10005];
    char s[105];
    int ans[10005][2],tot=0,g[10005][10];
     
    int dfs(int x)
    {
        for (int i=1;i<=g[x][0];++i)
        {
            int t=g[x][i];
            if (vis[t]) continue;
            vis[t]=1;
            if (!linker[t]||dfs(linker[t]))
            {
                linker[t]=x;
                linker[x]=t;
                return 1;
            }
        }
        return 0;
    }
     
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        F(i,1,n) F(j,1,m) id[i][j]=++cnt;
        F(i,1,n)
        {
            scanf("%s",s+1);
            F(j,1,m)
                if (s[j]=='#') a[i][j]=1;
        }
        F(i,1,n) F(j,1,m)
        if (!a[i][j]&&((i+j)%2)){
            int tx,ty;
            F(k,0,3)
            {
                tx=i+mov[k][0];ty=j+mov[k][1];
                if (tx>=1&&tx<=n&&ty>=1&&ty<=m&&!a[tx][ty])
                {
                    g[id[i][j]][++g[id[i][j]][0]]=id[tx][ty];
                    g[id[tx][ty]][++g[id[tx][ty]][0]]=id[i][j];
                }
            }
        }
        int cnt=0;
        F(i,1,n) F(j,1,m) if (!a[i][j]&&(i+j)%2)
        {
            memset(vis,0,sizeof vis);
            if (dfs(id[i][j])) cnt++;
        }
        F(i,1,n) F(j,1,m) if (!a[i][j])
        {
            memset(vis,0,sizeof vis);
            vis[id[i][j]]=1;
            if (!linker[id[i][j]]||dfs(linker[id[i][j]]))
            {
                tot++;
                ans[tot][0]=i;ans[tot][1]=j;
                linker[id[i][j]]=0;
            }
        }
        if (!tot) printf("LOSE
    ");
        else
        {
            printf("WIN
    ");
            F(i,1,tot) printf("%d %d
    ",ans[i][0],ans[i][1]);
        }
    }
    

      

  • 相关阅读:
    第17章—前端分页(Bootstrap-Table)
    第16章—日志(slf4j&logback)
    第15章—数据库连接池(DBCP2)
    第14章—数据库连接池(C3P0)
    第13章—数据库连接池(Druid)
    第00章—IDEA
    第12章—整合Redis
    第11章—常用注解(持续更新中)
    获取图片的宽高
    button按钮文字超出范围后省略号位置设置
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6545696.html
Copyright © 2011-2022 走看看