【bzoj2437】[Noi2011]兔兔与蛋蛋 二分图最大匹配+博弈论
Description

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≤ 40
Sample 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 3
Sample Output
样例一:
1
1
样例二:
0
样例三:
2
1
2
样例1对应图一中的游戏过程
样例2对应图三中的游戏过程
Sol
最近补了几发博弈论,但都是和sg函数有关的博弈,看到这题就懵了。
后来才知道这个叫二分图博弈......
具体地,这个操作相当于在移动这个空格,我们把空格变成黑色,那么就是按照黑白黑白黑白的顺序走,这好像有点二分图的感觉...
然后我们把合法的点拉出来建四联通的二分图(到起点的曼哈顿距离和它的颜色正好匹配),之后这个博弈其实就是在二分图上跑增广路,而且经过的边不能再次经过,这样的话我们发现,一个点是必胜态当且仅当这个点一定是一个最大匹配包含的点,因为匹配边和连接匹配的边总个数是个奇数。。。只要一直顺着匹配连边走就能赢。。。(对手走的是连接两对匹配的边)否则的话一定是必败态(因为走一步一定走到了一个最大匹配上,假设走不到说明还有新的匹配,与最大匹配矛盾,不成立)。
至于判断一个点是不是最大匹配的必需点,我们把它删掉,从它的原匹配点如果能找到最短路,说明它不是必需点。判断有没有做错是需要判断两个连续的状态是不是都是必胜态。。。
然后好像就完了......
Code
#include <bits/stdc++.h>
using namespace std;
char s[45][45];vector<int>e[2500];
int n,m,q,tot,Index,ans,a[45][45],sx,sy,u,v,vis[2500],match[2500],del[2500],win[2500];
bool dfs(int x)
{
for(int i=0;i<e[x].size();i++)
{
if(del[e[x][i]]||vis[e[x][i]]==Index) continue;
vis[e[x][i]]=Index;
if(!match[e[x][i]]||dfs(match[e[x][i]])){match[e[x][i]]=x,match[x]=e[x][i];return 1;}
}
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
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]=='.'){sx=i,sy=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(i-sx)+abs(j-sy))%2==1)||(s[i][j]=='X'&&(abs(i-sx)+abs(j-sy))%2==0)) a[i][j]=++tot;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if(a[i][j])
{
if(a[i-1][j]) e[a[i][j]].push_back(a[i-1][j]);if(a[i+1][j]) e[a[i][j]].push_back(a[i+1][j]);
if(a[i][j-1]) e[a[i][j]].push_back(a[i][j-1]);if(a[i][j+1]) e[a[i][j]].push_back(a[i][j+1]);
}
for(int i=1;i<=tot;i++) if(!match[i]) Index++,dfs(i);
scanf("%d",&q);q<<=1;
for(int i=1;i<=q;i++)
{
u=a[sx][sy];
if(match[u]) v=match[u],match[u]=match[v]=0,del[u]=1,Index++,win[i]=!dfs(v);
else del[u]=1,win[i]=0;
scanf("%d%d",&sx,&sy);
}
for(int i=1;i<=q;i++,i++) if(win[i]&&win[i+1]) ans++;
printf("%d\n",ans);
for(int i=1;i<=q;i++,i++) if(win[i]&&win[i+1]) printf("%d\n",(i+1)>>1);
}
【bzoj2437】[Noi2011]兔兔与蛋蛋 二分图最大匹配+博弈论的更多相关文章
- 【BZOJ2437】【NOI2011】兔兔与蛋蛋(博弈论,二分图匹配)
[BZOJ2437][NOI2011]兔兔与蛋蛋(博弈论,二分图匹配) 题面 BZOJ 题解 考虑一下暴力吧. 对于每个状态,无非就是要考虑它是否是必胜状态 这个直接用\(dfs\)爆搜即可. 这样子 ...
- 【BZOJ 2437】 2437: [Noi2011]兔兔与蛋蛋 (博弈+二分图匹配**)
未经博主同意不得转载 2437: [Noi2011]兔兔与蛋蛋 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 693 Solved: 442 Des ...
- bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势
noi2011 兔兔与蛋蛋 题目大意 直接看原题吧 就是\(n*m\)的格子上有一些白棋和一些黑棋和唯一一个空格 兔兔先手,蛋蛋后手 兔兔要把与空格相邻的其中一个白棋移到空格里 蛋蛋要把与空格相邻的其 ...
- BZOJ.2437.[NOI2011]兔兔与蛋蛋游戏(二分图博弈 匈牙利)
题目链接 首先空格的移动等价于棋子在黑白格交替移动(设起点移向白格就是黑色),且不会走到到起点距离为奇数的黑格.到起点距离为偶数的白格(删掉就行了),且不会重复走一个格子. (然后策略就同上题了,只不 ...
- 2437: [Noi2011]兔兔与蛋蛋 - BZOJ
Description Input 输入的第一行包含两个正整数 n.m.接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母" ...
- 博弈论(二分图匹配):NOI 2011 兔兔与蛋蛋游戏
Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母&quo ...
- NOI2011 兔兔与蛋蛋游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=2437 这道题真是极好的. 75分做法: 搜索. 出题人真的挺良心的,前15个数据点的范围都很小,可以 ...
- 【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)
[BZOJ2432][NOI2011]兔农(数论,矩阵快速幂) 题面 BZOJ 题解 这题\(75\)分就是送的,我什么都不想写. 先手玩一下,发现每次每次出现\(mod\ K=1\)的数之后 把它减 ...
- POJ 2226二分图最大匹配
匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图 ...
随机推荐
- 密码生成工具Cupp
Cupp可根据已知信息生成相应的字典,用来爆破很有帮助 首先先安装一下cupp 命令:apt-get install cupp 参数说明: -v查看cupp版本号 -h 查看参数列表 -l 从gith ...
- 使用原生js自定义内置标签
使用原生js自定义内置标签 效果图 代码 <!DOCTYPE html> <html lang="en"> <head> <meta ch ...
- leetcode709
string toLowerCase(string str) { transform(str.begin(), str.end(), str.begin(), ::tolower); return s ...
- Centos7下快速安装Mongo3.2
Centos7下快速安装Mongo3.2 一般安装Mongo推荐源码安装,有时候为了快部署测试环境,或者仅仅是想装个mongo shell,这时候yum安装是最合适的方式, 下面介绍一下如何在Cent ...
- C程序栈内存堆内存的地址
#include <stdio.h> #include <malloc.h> int main() { char * p1, * p2; p1=(char *)malloc(2 ...
- 游戏引擎架构Note1
[游戏引擎架构] 1.第14章介绍的对游戏性相关系统的设计非常有价值.各个开发人员几乎都是凭经验设计,很少见有书籍对这些做总结. 5.通过此书以知悉一些知名游戏作品实际上所采用的方案. 6.书名中的架 ...
- 算法优化》关于1D*1D的DP的优化
关于这一主题的DP问题的优化方法,我以前写过一篇博客与其有关,是关于对递推形DP的前缀和优化,那么这种优化方法就不再赘述了. 什么叫1D*1D的DP捏,就是一共有N种状态,而每种状态都要N种决策,这就 ...
- 【COCI2012】覆盖字符串
[题目描述] 给出一个长度为N的小写字母串,现在Mirko有M个若干长度为Li字符串.现在Mirko要用这M个字符串去覆盖给出的那个字符串的.覆盖时,必须保证:1.Mirko的字符串不能拆开,旋转:2 ...
- 什么是Kali Linux?
什么是Kali Linux? Kali Linux是一个基于Debian的Linux发行版,旨在实现高级渗透测试和安全审计.Kali包含数百种工具,适用于各种信息安全任务,如渗透测试,安全研究,计算机 ...
- 12.Alias(别名)
通过使用 SQL,可以为列名称和表名称指定别名(Alias). SQL Alias 表的 SQL Alias 语法 SELECT column_name(s) FROM table_name AS a ...