zoukankan      html  css  js  c++  java
  • 2019.01.06-dtoj-2437: [Noi2011]兔兔与蛋蛋

    题目描述:


    算法标签:二分图匹配

    思路:

    首先,看作是操作看成是空格移动,我叫空格的位置是起点。

    如果对整个棋盘进行黑白染色,即所以与起点所在格子同色的黑色棋子和与起点所在格子不同色的白色格子才可以走到。于是对于棋盘中的有效点进行黑白匹配,每次移动会使走的那个点变成无效点。于是每次在二分图匹配中删去一个点再继续匹配。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=45,M=1605,dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
    bool del[M],f[N][N],win[2005];char s[N][N];
    int n,m,id[N][N],tot,si,sj,nt,d[M],mat[M],head[M],ne[M<<1],to[M<<1],cnt;
    il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;}
    il void insert(int x,int y){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;}
    il bool dfs(int x){
        d[x]=nt;
        for(int i=head[x];i;i=ne[i]){
            if(del[to[i]]||d[to[i]]==nt)continue;
            d[to[i]]=nt;
            if(!mat[to[i]]||dfs(mat[to[i]])){
                mat[to[i]]=x;mat[x]=to[i];
                return 1;
            }
        }
        return 0;
    }
    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]=='.'){si=i;sj=j;s[i][j]='X';break;}
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){
            if(s[i][j]=='O'&&((abs(si-i)+abs(sj-j))&1))id[i][j]=++tot;
            if(s[i][j]=='X'&&((abs(si-i)+abs(sj-j))&1)==0)id[i][j]=++tot;
        }
        for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
            if(id[i][j])for(int k=0;k<4;k++){
                int xx=i+dx[k],yy=j+dy[k];
                if(id[xx][yy])insert(id[i][j],id[xx][yy]);
            }
        for(int i=1;i<=tot;i++)if(!mat[i])++nt,dfs(i);
        int q=read();q<<=1;
        for(int i=1;i<=q;i++){
            int x=id[si][sj];
            if(mat[x]){int v=mat[x];mat[x]=mat[v]=0;del[x]=1;nt++;win[i]=!dfs(v);}
            else del[x]=1;
            si=read(),sj=read();
        }
        int ans=0;for(int i=1;i<=q;i+=2)ans+=(win[i]&&win[i+1]);
        printf("%d
    ",ans);
        for(int i=1;i<=q;i+=2)if(win[i]&&win[i+1])printf("%d
    ",(i+1)>>1);
        return 0;
    }
    View Code

     

  • 相关阅读:
    MD5中使用16进制
    关于mysql函数GROUP_CONCAT
    一个不错的源码网站
    查看jdk 线程 日志
    list 的sublist 隐藏 bug
    web 环境项目(intellj部署的tomcat) 重启时报 Exception in thread "HouseKeeper" java.lang.NullPointerException
    怎么给已有项目引入别的项目
    javascript 和 CoffeeScript 里的类
    express 与 mvc
    express的路由
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10230686.html
Copyright © 2011-2022 走看看