【BZOJ 2437】 2437: [Noi2011]兔兔与蛋蛋 (博弈+二分图匹配**)
未经博主同意不得转载
2437: [Noi2011]兔兔与蛋蛋
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 693 Solved: 442Description
Input
输入的第一行包含两个正整数 n、m。
接下来 n行描述初始棋盘。其中第i 行包含 m个字符,每个字符都是大写英文字母"X"、大写英文字母"O"或点号"."之一,分别表示对应的棋盘格中有黑色棋子、有白色棋子和没有棋子。其中点号"."恰好出现一次。
接下来一行包含一个整数 k(1≤k≤1000) ,表示兔兔和蛋蛋各进行了k次操作。
接下来 2k行描述一局游戏的过程。其中第 2i – 1行是兔兔的第 i 次操作(编号为i的操作) ,第2i行是蛋蛋的第i次操作。每个操作使用两个整数x,y来描述,表示将第x行第y列中的棋子移进空格中。
输入保证整个棋盘中只有一个格子没有棋子, 游戏过程中兔兔和蛋蛋的每个操作都是合法的,且最后蛋蛋获胜。Output
输出文件的第一行包含一个整数r,表示兔兔犯错误的总次数。
接下来r 行按递增的顺序给出兔兔“犯错误”的操作编号。其中第 i 行包含一个整数ai表示兔兔第i 个犯错误的操作是他在游戏中的第 ai次操作。
1 ≤n≤ 40, 1 ≤m≤ 40Sample Input
样例一:
1 6
XO.OXO
1
1 2
1 1
样例二:
3 3
XOX
O.O
XOX
4
2 3
1 3
1 2
1 1
2 1
3 1
3 2
3 3
样例三:
4 4
OOXX
OXXO
OO.O
XXXO
2
3 2
2 2
1 2
1 3Sample Output
样例一:
1
1
样例二:
0
样例三:
2
1
2样例1对应图一中的游戏过程
样例2对应图三中的游戏过程HINT
Source
【分析】
神题。。
首先。。博弈部分,用二分图匹配来做。
题目可以看成是空白格在移动。因为是白黑白黑地走,显然呢是有一些点是无用的。比如距离起始点为偶数格的白点。。
然后剩下的点分两块,黑点和白点,弄成二分图,相邻的黑白点连边,一开始的空白格可以看成是黑点。
想想白怎么样能赢呢?就是走到一个白点,然后你有方式无论黑怎么走你都能使结束点在白点。
然后就有一个结论:
如果当前所在的点是必须点,那么必胜。否则必败。
必须点指的是这个点一定在所有可能的最大二分图匹配中。非必需点是它的补集。
为什么呢?【下面只说你怎么赢和你为什么不会输】
首先说必须点必胜。

从必须点出发,你的策略是每次都走匹配边(选择任意一个最大匹配就好),那么别人就一定走的是非匹配边嘛。
一定是在匹配边结束(结束指找不到别的没走过的边走了)。否则,如右图,那么这条路的匹配边和非匹配边互换,又是一个最大二分匹配,那么一开始的必须点不用选择,与其必须点的身份矛盾,是不可能的。
然后是非必须点必败。

这时后手掌握必胜态。你从非必须点出发,一定走到了一条在某最大匹配方案中的非匹配边(因为是非必须点),那么别人就根据这个最大匹配的方案每次走匹配边。
一定是在匹配边结束。否则,如右图,那么这条路的匹配边和非匹配边互换,是可以交替的增广路,与其最大匹配的身份矛盾,是不可能的。
所以判断胜负只要判断当前所在点是否必须。
打法见代码【膜大颓果漂亮打法】,比我之前想的好多了。判断是否必须点,只要删掉这个点,看看还能不能增广就好了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 50
#define Maxq 2010 int n,m; struct node
{
int x,y,next;
}t[Maxn*Maxn*];
int first[Maxn*Maxn],len; void ins(int x,int y)
{
t[++len].x=x;t[len].y=y;
t[len].next=first[x];first[x]=len;
} int a[Maxn][Maxn],num[Maxn][Maxn];
int tot; int match[Maxn*Maxn],chw[Maxn*Maxn];
bool vis[Maxn*Maxn]; bool ffind(int x,int nt)
{
if(!vis[x]) return ;
for(int i=first[x];i;i=t[i].next) if(chw[t[i].y]!=nt&&vis[t[i].y])
{
int y=t[i].y;
chw[y]=nt;
if(!match[y]||ffind(match[y],nt))
{
match[y]=x;match[x]=y;
return ;
}
}
return ;
} int nt,op[Maxn*Maxn];
int bx[]={,,,-,},
by[]={,,,,-};
char s[Maxn]; bool ret[Maxn*Maxn]; int nx,ny;
void get_ans()
{
memset(match,,sizeof(match));
memset(chw,,sizeof(chw));
nt=;
for(int i=;i<=tot;i++) vis[i]=;
for(int i=;i<=tot;i++) if(!match[i])
{
nt++;
ffind(i,nt);
}
int q;
scanf("%d",&q);q<<=;
op[]=;
for(int i=;i<=q;i++)
{
vis[num[nx][ny]]=;
if(match[num[nx][ny]])
{
int nw=match[num[nx][ny]];
match[nw]=match[num[nx][ny]]=;
ret[i]=!ffind(nw,++nt);//找不到 必须点 必胜
}
else
{
ret[i]=;//不在最优匹配中 不是必须点 必败
}
scanf("%d%d",&nx,&ny);
}
for(int i=;i<=q;i+=)
if(ret[i]&&ret[i+]) op[++op[]]=(i+)/;
printf("%d\n",op[]);
for(int i=;i<=op[];i++) printf("%d\n",op[i]);
} int main()
{
scanf("%d%d",&n,&m);
len=;tot=;
for(int i=;i<=n;i++)
{
scanf("%s",s+);
for(int j=;j<=m;j++)
{
if(s[j]=='X') a[i][j]=;
else if(s[j]=='O') a[i][j]=;
else a[i][j+]=,nx=i,ny=j;
num[i][j]=++tot;
}
}
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
for(int k=;k<=;k++)
{
int xx=i+bx[k],yy=j+by[k];
if(xx<||yy<||xx>n||yy>m) continue;
if(a[xx][yy]==a[i][j]) continue;
ins(num[i][j],num[xx][yy]);
}
}
get_ans();
return ;
}
2017-03-30 12:52:17
【BZOJ 2437】 2437: [Noi2011]兔兔与蛋蛋 (博弈+二分图匹配**)的更多相关文章
- BZOJ2437 NOI2011兔兔与蛋蛋(二分图匹配+博弈)
首先将棋盘黑白染色,不妨令空格处为黑色.那么移动奇数次后空格一定处于白色格子,偶数次后空格一定处于黑色格子.所以若有某个格子的棋子颜色与棋盘颜色不同,这个棋子就是没有用的.并且空格与某棋子交换后,棋子 ...
- BZOJ 3168 Luogu P4100 [HEOI2013]钙铁锌硒维生素 (矩阵求逆、二分图匹配)
线性代数+图论好题. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3168 (luogu) https://www.lu ...
- bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势
noi2011 兔兔与蛋蛋 题目大意 直接看原题吧 就是\(n*m\)的格子上有一些白棋和一些黑棋和唯一一个空格 兔兔先手,蛋蛋后手 兔兔要把与空格相邻的其中一个白棋移到空格里 蛋蛋要把与空格相邻的其 ...
- 2437: [Noi2011]兔兔与蛋蛋 - BZOJ
Description Input 输入的第一行包含两个正整数 n.m.接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母" ...
- NOI2011 兔兔与蛋蛋游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=2437 这道题真是极好的. 75分做法: 搜索. 出题人真的挺良心的,前15个数据点的范围都很小,可以 ...
- 【BZOJ2437】【NOI2011】兔兔与蛋蛋(博弈论,二分图匹配)
[BZOJ2437][NOI2011]兔兔与蛋蛋(博弈论,二分图匹配) 题面 BZOJ 题解 考虑一下暴力吧. 对于每个状态,无非就是要考虑它是否是必胜状态 这个直接用\(dfs\)爆搜即可. 这样子 ...
- bzoj 2437 [Noi2011]兔子和鸡蛋 [二分图匹配]
叙述性说明 这些日子.兔子和蛋像一个新的棋盘游戏. 这场比赛是在 n 行 m 在船上进行列. 前,棋盘上有一 个格子是空的,其他的格子中都放置了一枚棋子,棋子或者是黑色,或者是白色. 每一局游戏总是兔 ...
- 【bzoj2437】[Noi2011]兔兔与蛋蛋 二分图最大匹配+博弈论
Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母&quo ...
- 【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)
[BZOJ2432][NOI2011]兔农(数论,矩阵快速幂) 题面 BZOJ 题解 这题\(75\)分就是送的,我什么都不想写. 先手玩一下,发现每次每次出现\(mod\ K=1\)的数之后 把它减 ...
随机推荐
- (4.1)LingPipe在Eclipse中的运行
酒店评论情感分析系统(四)——LingPipe在Eclipse中的运行 本来打算在做这个项目的时候,使用基于语义的文本倾向性分析方法,即先通过对评论文本进行中文分析,去停用词,然后在倾向性语义模式库的 ...
- [php]http响应头解析
(Status-Line) HTTP/ OK Cache-Control no-cache Content-Length Content-Type image/gif Date Sat, Dec :: ...
- 【BZOJ】3173: [Tjoi2013]最长上升子序列(树状数组)
[题意]给定ai,将1~n从小到大插入到第ai个数字之后,求每次插入后的LIS长度. [算法]树状数组||平衡树 [题解] 这是树状数组的一个用法:O(n log n)寻找前缀和为k的最小位置.(当数 ...
- 【洛谷 P4291】 [HAOI2008]排名系统(Splay,Trie)
题目链接 不是双倍经验我会去\(debug\)一上午? 一开始我是用的\(map+string\),跑的太慢了,T了4个点. 后来我手写了\(string\),重载了小于号,依然用的\(map\),T ...
- 49、是否使用过functools中的函数?其作用是什么?
functools模块介绍 functools用于高阶函数:指那些作用于函数或者返回其他函数的函数.通常情况下,只要是可以被当做函数调用的对象就是这个模块的目标. functools模块的功能 pyt ...
- oracle数据库只查询前n条
select * from (select * from tablename order by createdate desc) aaa -- 按创建时间倒排序 where rownum &l ...
- Mysql储存过程7: case
#用在储存过程中: create procedure k() begin declare number int; )); case number then select '>0'; else s ...
- sea.js中的checkbox批量操作
<table width="100%" border="0" cellspacing="0" cellpadding="0& ...
- [转载]FFmpeg完美入门[1] - FFmpeg介绍及安装
1 FFmpeg简介 FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视 频的完整解决方案.它包含了非常先 ...
- Python实现好友全头像的拼接
微信好友全头像 话不多说,直接上代码 import itchat import math import PIL.Image as Image import os itchat.auto_login() ...

