未经博主同意不得转载

2437: [Noi2011]兔兔与蛋蛋

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 693  Solved: 442

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对应图三中的游戏过程

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]兔兔与蛋蛋 (博弈+二分图匹配**)的更多相关文章

  1. BZOJ2437 NOI2011兔兔与蛋蛋(二分图匹配+博弈)

    首先将棋盘黑白染色,不妨令空格处为黑色.那么移动奇数次后空格一定处于白色格子,偶数次后空格一定处于黑色格子.所以若有某个格子的棋子颜色与棋盘颜色不同,这个棋子就是没有用的.并且空格与某棋子交换后,棋子 ...

  2. BZOJ 3168 Luogu P4100 [HEOI2013]钙铁锌硒维生素 (矩阵求逆、二分图匹配)

    线性代数+图论好题. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3168 (luogu) https://www.lu ...

  3. bzoj 2437[Noi2011]兔兔与蛋蛋 黑白染色二分图+博弈+匈牙利新姿势

    noi2011 兔兔与蛋蛋 题目大意 直接看原题吧 就是\(n*m\)的格子上有一些白棋和一些黑棋和唯一一个空格 兔兔先手,蛋蛋后手 兔兔要把与空格相邻的其中一个白棋移到空格里 蛋蛋要把与空格相邻的其 ...

  4. 2437: [Noi2011]兔兔与蛋蛋 - BZOJ

    Description Input 输入的第一行包含两个正整数 n.m.接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母" ...

  5. NOI2011 兔兔与蛋蛋游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=2437 这道题真是极好的. 75分做法: 搜索. 出题人真的挺良心的,前15个数据点的范围都很小,可以 ...

  6. 【BZOJ2437】【NOI2011】兔兔与蛋蛋(博弈论,二分图匹配)

    [BZOJ2437][NOI2011]兔兔与蛋蛋(博弈论,二分图匹配) 题面 BZOJ 题解 考虑一下暴力吧. 对于每个状态,无非就是要考虑它是否是必胜状态 这个直接用\(dfs\)爆搜即可. 这样子 ...

  7. bzoj 2437 [Noi2011]兔子和鸡蛋 [二分图匹配]

    叙述性说明 这些日子.兔子和蛋像一个新的棋盘游戏. 这场比赛是在 n 行 m 在船上进行列. 前,棋盘上有一 个格子是空的,其他的格子中都放置了一枚棋子,棋子或者是黑色,或者是白色. 每一局游戏总是兔 ...

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

    Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母&quo ...

  9. 【BZOJ2432】【NOI2011】兔农(数论,矩阵快速幂)

    [BZOJ2432][NOI2011]兔农(数论,矩阵快速幂) 题面 BZOJ 题解 这题\(75\)分就是送的,我什么都不想写. 先手玩一下,发现每次每次出现\(mod\ K=1\)的数之后 把它减 ...

随机推荐

  1. ⑦ 设计模式的艺术-13.代理(Proxy)模式

    为什么需要代理模式 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口. 开闭原则,增加 ...

  2. Go语言 7 并发编程

    文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ Go学习群:415660935 今天我们学习Go语言编程的第七章,并发编程.语言级别 ...

  3. 如何通过掩码计算可用的IP数量

    假设掩码是28,28也就是28个1.本身掩码是255.255.255.255那么转换成二进制也就是 11111111,11111111,11111111,11111111 那么28个1也就是: 111 ...

  4. RTC

    RTC的英文全称是Real-Time Clock,翻译过来是实时时钟芯片. RTC是PC主板上的晶振及相关电路组成的时钟电路的生成脉冲主板上的晶振及相关电路组成的时钟电路的生成脉冲,,RTC经过825 ...

  5. usb_submit_urb 解释的够够的

    /** * usb_submit_urb - issue an asynchronous transfer request for an endpoint * @urb: pointer to the ...

  6. PyQt:eg4

    import sys from PyQt4 import QtCore from PyQt4 import QtGui class Form(QtGui.QDialog): def __init__( ...

  7. java基础8 构造函数和构造代码块

    一.构造函数 1 构造函数的作用 给对应的对象进行初始化. 2 构造函数的格式 修饰符 函数名(形式参数){ //函数名就是类名 函数体 } 举例说明: class Perosn{ private i ...

  8. Codeforces 918C The Monster(括号匹配+思维)

    题目链接:http://codeforces.com/contest/918/problem/C 题目大意:给你一串字符串,其中有'('.')'.'?'三种字符'?'可以当成'('或者')'来用,问该 ...

  9. 用socket发送匿名邮件之python实现

    发送邮件可以用smtp协议,整个过程为: 用户代理(user-agent,比如outlook.foxmail等邮件客户端)---(smtp协议)--->本地邮件服务器 --- (smtp协议)- ...

  10. 洛谷P1554 梦中的统计 题解

    题目传送门 这道题暴力又让我过了...数据真的很水(luogu) 暴力枚举n~m的每个数,再统计一次,交付评测...AC #include<bits/stdc++.h> using nam ...