NOI2011真题:兔兔与蛋蛋游戏
NOI2011真题:兔兔与蛋蛋游戏
题目描述
这些天,兔兔和蛋蛋喜欢上了一种新的棋类游戏。
这个游戏是在一个 n行 m 列的棋盘上进行的。游戏开始之前,棋盘上有一个格子是空的,其它的格子中都放置了一枚棋子,棋子或者是黑色,或者是白色。
每一局游戏总是兔兔先操作,之后双方轮流操作,具体操作为:
·兔兔每次操作时,选择一枚与空格相邻的白色棋子,将它移进空格。
·蛋蛋每次操作时,选择一枚与空格相邻的黑色棋子,将它移进空格。
第一个不能按照规则操作的人输掉游戏。为了描述方便,下面将操作“将第x行第y列中的棋子移进空格中”记为 M(x,y)M(x,y)。
例如下面是三个游戏的例子。

最近兔兔总是输掉游戏,而且蛋蛋格外嚣张,于是兔兔想请她的好朋友——你——来帮助她。她带来了一局输给蛋蛋的游戏的实录,请你指出这一局游戏中所有她“犯错误”的地方。
注意:
·两个格子相邻当且仅当它们有一条公共边。
·兔兔的操作是“犯错误”的,当且仅当,在这次操作前兔兔有必胜策略,而这次操作后蛋蛋有必胜策略。
输入格式
输入的第一行包含两个正整数 n,m。
接下来 n 行描述初始棋盘。其中第 i 行包含 m个字符,每个字符都是大写英文字母 X、大写英文字母 O 或点号 . 之一,分别表示对应的棋盘格中有黑色棋子、有白色棋子和没有棋子。其中点号 . 恰好出现一次。
接下来一行包含一个整数 k(1≤k≤1000) ,表示兔兔和蛋蛋各进行了 k 次操作。
接下来 2k 行描述一局游戏的过程。其中第 2i – 1 行是兔兔的第 i 次操作(编号为 i 的操作) ,第 2i 行是蛋蛋的第 i 次操作。每个操作使用两个整数 x,y 来描述,表示将第 x 行第 y列中的棋子移进空格中。
输入保证整个棋盘中只有一个格子没有棋子, 游戏过程中兔兔和蛋蛋的每个操作都是合法的,且最后蛋蛋获胜。
输出格式
输出文件的第一行包含一个整数 r,表示兔兔犯错误的总次数。
接下来 r行按递增的顺序给出兔兔“犯错误”的操作编号。其中第 i 行包含一个整数ai表示兔兔第 i 个犯错误的操作是他在游戏中的第 ai次操作。
输入样例:
1 6
XO.OXO
1
1 2
1 1
输出样例:
1
1
说明提示:

解法:
知识:二分图,博弈论,深度优先搜索
先审清楚题意。A 一步走错的判定:A 走这步之前,A先手采用最优策略必胜;A 走这步之后,B先手采用最优策略必胜。
判断的过程:强制当前点不选,如果它的匹配点仍然能找到新的匹配点,说明有一种最大匹配不包含它,自然它就不是 一定 在最大匹配中。
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN=41,MAXS=1601,MAXK=1001;
int n,m,dx[]={0,0,1,-1},dy[]={1,-1,0,0};
int tar[MAXS];
bool vis[MAXS],win[MAXK];
bool bel[MAXN][MAXN],col[MAXN][MAXN],del[MAXS];
vector <int> edge[MAXS],src;
inline int id(int x,int y) {
if(x<1||x>n||y<1||y>m||bel[x][y]!=col[x][y]) return -1;
return (x-1)*m+y;
}
inline bool match(int p) {
if(del[p]) return false;
for(int x:edge[p]) {
if(vis[x]||del[x]) continue;
vis[x]=true;
if(tar[x]==-1||match(tar[x])) {
tar[x]=p;
return true;
}
}
return false;
}
inline int MM() {
int ret=0;
memset(tar,-1,sizeof(tar));
for(int x:src) {
memset(vis,false,sizeof(vis));
if(match(x)) ++ret;
}
return ret;
}
signed main() {
int kx,ky;
cin>>n>>m;
for(int i=1;i<=n;++i) {
for(int j=1;j<=m;++j) {
char ch;
cin>>ch;
if(ch=='.') kx=i,ky=j,bel[i][j]=true;
else bel[i][j]=(ch=='X');
}
}
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) col[i][j]=((i+j)%2==(kx+ky)%2);
for(int i=1;i<=n;++i) {
for(int j=1;j<=m;++j) {
if(bel[i][j]&&col[i][j]) {
src.push_back(id(i,j));
for(int k:{0,1,2,3}) {
int x=i+dx[k],y=j+dy[k];
if(id(x,y)!=-1) {
edge[id(i,j)].push_back(id(x,y));
}
}
}
}
}
int stdv=MM(),k;
del[id(kx,ky)]=true;
int tmpv=MM();
win[1]=tmpv!=stdv;
stdv=tmpv;
scanf("%d",&k);
vector <int> ans;
for(int i=1;i<=k;++i) {
int tx,ty;
scanf("%d%d",&tx,&ty);
del[id(tx,ty)]=true;
tmpv=MM();
win[i*2]=tmpv!=stdv;
stdv=tmpv;
if(win[i*2]&&win[i*2-1]) ans.push_back(i);
scanf("%d%d",&tx,&ty);
del[id(tx,ty)]=true;
tmpv=MM();
win[i*2+1]=tmpv!=stdv;
stdv=tmpv;
}
printf("%d\n",(int)ans.size());
for(int p:ans) printf("%d\n",p);
return 0;
}
NOI2011真题:兔兔与蛋蛋游戏的更多相关文章
- NOI2011 兔兔与蛋蛋游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=2437 这道题真是极好的. 75分做法: 搜索. 出题人真的挺良心的,前15个数据点的范围都很小,可以 ...
- 【BZOJ 2437】 2437: [Noi2011]兔兔与蛋蛋 (博弈+二分图匹配**)
未经博主同意不得转载 2437: [Noi2011]兔兔与蛋蛋 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 693 Solved: 442 Des ...
- 2437: [Noi2011]兔兔与蛋蛋 - BZOJ
Description Input 输入的第一行包含两个正整数 n.m.接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母" ...
- 【BZOJ2437】【NOI2011】兔兔与蛋蛋(博弈论,二分图匹配)
[BZOJ2437][NOI2011]兔兔与蛋蛋(博弈论,二分图匹配) 题面 BZOJ 题解 考虑一下暴力吧. 对于每个状态,无非就是要考虑它是否是必胜状态 这个直接用\(dfs\)爆搜即可. 这样子 ...
- 【bzoj2437】[Noi2011]兔兔与蛋蛋 二分图最大匹配+博弈论
Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母&quo ...
- bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势
noi2011 兔兔与蛋蛋 题目大意 直接看原题吧 就是\(n*m\)的格子上有一些白棋和一些黑棋和唯一一个空格 兔兔先手,蛋蛋后手 兔兔要把与空格相邻的其中一个白棋移到空格里 蛋蛋要把与空格相邻的其 ...
- 博弈论(二分图匹配):NOI 2011 兔兔与蛋蛋游戏
Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母&quo ...
- 第三届蓝桥杯 c/c++真题
第三届蓝桥杯真题 c/c++ 以下题目我自己也并不是所有的题目都是一次性就能做对或是有结题思路的.有些题目也是经过查证网上相关的资料或是参考了别人的代码和解题思路才做出来的.总的来看,这份题目考了很多 ...
- 蓝桥杯java历年真题及答案整理1~20.md
蓝桥杯java历年真题及答案整理(闭关一个月,呕心沥血整理出来的) 1 算法是这样的,如果给定N个不同字符,将这N个字符全排列,最终的结果将会是N!种.如:给定 A.B.C三个不同的字符,则结果为:A ...
- Noip前的大抱佛脚----Noip真题复习
Noip前的大抱佛脚----Noip真题复习 Tags: Noip前的大抱佛脚 Noip2010 题目不难,但是三个半小时的话要写四道题还是需要码力,不过按照现在的实力应该不出意外可以AK的. 机器翻 ...
随机推荐
- 记一次Linux光盘救援
最近遇到一个zz把/etc/profile改坏了导致系统起不来,所以复习一下光盘救援 工具:vm-workstation,centos6 原系统盘起不来后,插入有救援工具的系统盘后 按照提示进入she ...
- 插入排序C语言版本
算法思路: 每趟将一个待排序的元素作为关键字,按照其关键字值的大小插入到已经排好的部分的适当位置上,直到插入完成. 数组中待排序的关键字前面的数据为已经排序的数据,关键字插 ...
- Windows Powershell 对于布尔值的处理
Windows PowerShell中有很多场景需要输入0或者1作为命令的参数.Powershell对于布尔值的逻辑处理究竟是怎样的呢?除了最常用的$True, $False, 1, 0.对于要求输入 ...
- 使用 Loki 收集 nginx 日志
转载自:https://mp.weixin.qq.com/s?__biz=MzU4MjQ0MTU4Ng==&mid=2247492075&idx=1&sn=ba63984111 ...
- Elasticsearch 索引生命周期管理 ILM 实战指南
文章转载自:https://mp.weixin.qq.com/s/7VQd5sKt_PH56PFnCrUOHQ 1.什么是索引生命周期 在基于日志.指标.实时时间序列的大型系统中,集群的索引也具备类似 ...
- [基础] BS/CS 区别 Http/Https 区别 中间件请求
BS和CS的区别: 1.BS结构:Browser-Server-从浏览器到服务器,浏览器打开的所有内容都属于BS(三大主流浏览器Safari.Chrome和Firefo) 2.CS结构:Cli ...
- PAT (Basic Level) Practice 1024 科学计数法 分数 20
科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [+-][1-9].[0-9]+E[+-][0-9]+,即数字的整数部分只有 1 位,小数部分至少有 1 位,该数字及其指 ...
- PAT (Basic Level) Practice 1010 一元多项式求导 分数 25
设计函数求一元多项式的导数.(注:xn(n为整数)的一阶导数为nxn−1.) 输入格式: 以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过 1000 的整数).数字间以空格分隔. 输出格式: ...
- POJ2955 Brackets (区间DP)
很好的区间DP题. 需要注意第一种情况不管是否匹配,都要枚举k来更新答案,比如: "()()()":dp[0][5]=dp[1][4]+2=4,枚举k,k=1时,dp[0][1]+ ...
- Tomcat实战之路
目录 第一节.安装升级 1.1.linux初始化 1.2.安装 1.3.升级 第二节.配置 2.1.虚拟主机 2.2.默认网站首页路径 2.3.跳转 2.4.配置Tomcat日志 第三节.安全 3.1 ...