博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ2437 NOI2011兔兔与蛋蛋(二分图匹配+博弈)
阅读量:5161 次
发布时间:2019-06-13

本文共 2562 字,大约阅读时间需要 8 分钟。

  首先将棋盘黑白染色,不妨令空格处为黑色。那么移动奇数次后空格一定处于白色格子,偶数次后空格一定处于黑色格子。所以若有某个格子的棋子颜色与棋盘颜色不同,这个棋子就是没有用的。并且空格与某棋子交换后,棋子所在的格子改变使得该棋子与棋盘颜色不同,那么该棋子也会变为无用棋子。那么问题变为空格在棋盘上黑白格子交替移动,棋盘上有障碍物,走过的格子不能再走,不能移动者输。

  显然这是一个二分图博弈。如果所有的最大匹配都包含起点,先手必胜,因为每次只需要沿匹配边走即可,由增广路定理不会出现没边走的情况。否则后手必胜,因为一旦起点不在最大匹配中,走了一条边后后手变成先手,所达点一定在(不包含起点的)最大匹配中。那么每次我们只需要判断空格位置是否处于剩余图的所有最大匹配中,也即判断删除该点后最大匹配是否会减少。这只需要从被删除点原本的匹配点出发找增广路。判断完每次操作后是否处于必胜态后只要看是否从必胜态走到了必胜态即可。

#include
#include
#include
#include
#include
#include
using namespace std;#define ll long long#define N 42char getc(){ char c=getchar();while (c==10||c==13||c==32) c=getchar();return c;}int gcd(int n,int m){ return m==0?n:gcd(m,n%m);}int read(){ int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') { if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f;}int n,m,k,X,Y,a[N][N],p[N*N],match[N*N],id[N][N],cnt,t,ans;bool flag[N*N],tag[N*N],win[2010];int wx[4]={ 0,0,1,-1},wy[4]={ 1,-1,0,0};struct data{ int to,nxt;}edge[N*N<<2];void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}bool hungary(int k){ for (int i=p[k];i;i=edge[i].nxt) if (!flag[edge[i].to]&&!tag[edge[i].to]) { int x=edge[i].to; flag[x]=1; if (!match[x]||!tag[match[x]]&&hungary(match[x])) { match[x]=k,match[k]=x; return 1; } } return 0;}int main(){#ifndef ONLINE_JUDGE freopen("bzoj2437.in","r",stdin); freopen("bzoj2437.out","w",stdout); const char LL[]="%I64d\n";#else const char LL[]="%lld\n";#endif n=read(),m=read(); for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) { char c=getc(); a[i][j]=c=='O'; if (c=='.') X=i,Y=j; } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) for (int k=0;k<4;k++) if (i+wx[k]>=1&&i+wx[k]<=n&&j+wy[k]>=1&&j+wy[k]<=m&& (abs(i-X)+abs(j-Y)&1)==a[i][j]&&(abs(i+wx[k]-X)+abs(j+wy[k]-Y)&1)==a[i+wx[k]][j+wy[k]]) { if (!id[i][j]) id[i][j]=++cnt;if (!id[i+wx[k]][j+wy[k]]) id[i+wx[k]][j+wy[k]]=++cnt; addedge(id[i][j],id[i+wx[k]][j+wy[k]]),addedge(id[i+wx[k]][j+wy[k]],id[i][j]); } for (int i=1;i<=cnt;i++) if (!match[i]) memset(flag,0,sizeof(flag)),hungary(i); tag[id[X][Y]]=1; if (match[id[X][Y]]) { memset(flag,0,sizeof(flag)); match[match[id[X][Y]]]=0; win[0]=!hungary(match[id[X][Y]]); } int k=read()<<1; for (int i=1;i<=k;i++) { int x=read(),y=read(); tag[id[x][y]]=1; if (match[id[x][y]]) { memset(flag,0,sizeof(flag)); match[match[id[x][y]]]=0; win[i]=!hungary(match[id[x][y]]); } } int tot=0; for (int i=0;i
>1)+1); return 0;}

 

转载于:https://www.cnblogs.com/Gloid/p/9915230.html

你可能感兴趣的文章
java之struts2的数据处理
查看>>
java之struts框架入门教程
查看>>
B. An express train to reveries(Round 418)
查看>>
不要逼孩子考100分
查看>>
Python(四)
查看>>
Symbols of String Pattern Matching
查看>>
如何判断一个人的能力
查看>>
【学习笔记】 狄利克雷与莫比乌斯
查看>>
关于 DataRow 中为 DataRowState.Deleted 状态的 字段列值取值方法
查看>>
724.Find Pivot Index
查看>>
小牛必会之—monkey
查看>>
python3.6.3安装步骤,适用linux centos系统
查看>>
没有终结点在侦听可以接受消息的*这通常是由于不正确的地址或者 SOAP操作导致的...
查看>>
HTML5---15.网络接口
查看>>
接收xml请求流并解析字符串的例子
查看>>
中文字符串分隔的注意问题
查看>>
zip打包是去掉路径
查看>>
常用的经典jquery代码[转]
查看>>
正则判断
查看>>
转--RTP如何打包H264数据
查看>>