bzoj2437 [Noi2011]兔兔与蛋蛋

二分图博弈果然都是一个套路,必经点必胜,非必经点必败,

但是肯定不能没走一步就重新建图判断必胜还是必败,那么我们可以这样:每走一步就把这个点删掉,然后find他原来的匹配,如果找不到,就说明他是必经点,否则就是非必经点。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <cmath>
 6 #define N 1601
 7 using namespace std;
 8 int e=1,head[N];
 9 struct edge{int v,next;}ed[N*4];
10 void add(int u,int v){ed[e].v=v;ed[e].next=head[u];head[u]=e++;}
11 int pp[N],del[N],id[41][41];
12 bool vis[N],ans[N];
13 bool find(int x){
14     for(int i=head[x];i;i=ed[i].next){
15         int v=ed[i].v;
16         if(del[v]||vis[v])continue;vis[v]=1;
17         if(!pp[v]||find(pp[v])){
18             pp[v]=x;pp[x]=v;
19             return 1;
20         }
21     }return 0;
22 }
23 int a[41][41],be,n,m,T,sx,sy,tot1,tot2,tot;
24 char ch[41];
25 bool check(int i,int j){return ((i+j)&1)^a[i][j]==be;}
26 int f[N],f_cnt;
27 int main(){
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=n;i++){
30         scanf("%s",ch+1);
31         for(int j=1;j<=m;j++)
32             if(ch[j]==‘O‘)a[i][j]=1;
33             else if(ch[j]==‘X‘)a[i][j]=0;
34             else sx=i,sy=j;
35     }
36     be=(sx+sy)&1;
37     for(int i=1;i<=n;i++)
38         for(int j=1;j<=m;j++)if(check(i,j))
39             if(a[i][j])id[i][j]=++tot1;
40             else id[i][j]=++tot2;
41     for(int i=1;i<=n;i++)
42         for(int j=1;j<=m;j++)if(check(i,j)&&(!a[i][j]))
43             id[i][j]+=tot1;
44     tot=tot1+tot2;
45     for(int i=1;i<=n;i++)
46         for(int j=1;j<=m;j++)if(id[i][j]){
47             if(id[i+1][j])add(id[i][j],id[i+1][j]);
48             if(id[i][j+1])add(id[i][j],id[i][j+1]);
49             if(id[i-1][j])add(id[i][j],id[i-1][j]);
50             if(id[i][j-1])add(id[i][j],id[i][j-1]);
51         }
52     for(int i=1;i<=tot1;i++){
53         memset(vis,0,sizeof vis);
54         find(i);
55     }
56     scanf("%d",&T);T<<=1;
57     for(int i=1,x,y;i<=T;i++){
58         int now=id[sx][sy],p=pp[now];
59         del[now]=1;pp[now]=pp[p]=0;
60         if(!p)ans[i]=0;
61         else{
62             memset(vis,0,sizeof vis);
63             ans[i]=find(p)^1;
64         }
65         scanf("%d%d",&sx,&sy);
66     }
67     for(int i=1;i<=T;i+=2)
68         if(ans[i]&&ans[i+1])f[++f_cnt]=(i+1)>>1;
69     printf("%d\n",f_cnt);
70     for(int i=1;i<=f_cnt;i++)
71         printf("%d\n",f[i]);
72     return 0;
73 }

原文地址:https://www.cnblogs.com/Ren-Ivan/p/8352969.html

时间: 2024-12-23 12:37:33

bzoj2437 [Noi2011]兔兔与蛋蛋的相关文章

NOI2011 兔兔与蛋蛋游戏

http://www.lydsy.com/JudgeOnline/problem.php?id=2437 这道题真是极好的. 75分做法: 搜索. 出题人真的挺良心的,前15个数据点的范围都很小,可以直接搜索. #include<cstdio> #include<cstdlib> #include<iostream> #include<fstream> #include<algorithm> #include<cstring> #in

bzoj 2437 [Noi2011]兔兔与蛋蛋 [二分图匹配]

描述 这些天,兔兔和蛋蛋喜欢上了一种新的棋类游戏. 这个游戏是在一个 n 行 m 列的棋盘上进行的.游戏开始之前,棋盘上有一 个格子是空的,其它的格子中都放置了一枚棋子,棋子或者是黑色,或者是白色. 每一局游戏总是兔兔先操作,之后双方轮流操作,具体操作为: 兔兔每次操作时,选择一枚与空格相邻的白色棋子,将它移进空格. 蛋蛋每次操作时,选择一枚与空格相邻的黑色棋子,将它移进空格. 第一个不能按照规则操作的人输掉游戏. 最近兔兔总是输掉游戏,而且蛋蛋格外嚣张,于是兔兔想请她的好朋友-- 你--来帮助

【博弈+二分图匹配】[NOI2011]兔兔与蛋蛋游戏

题目描述 Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母"O"或点号"."之一,分别表示对应的棋盘格中有黑色棋子.有白色棋子和没有棋子.其中点号"."恰好出现一次. 接下来一行包含一个整数 k(1≤k≤1000) ,表示兔兔和蛋蛋各进行了k次操作. 接下来 2k行描述一局游戏的过程.其中第 2i – 1

博弈论(二分图匹配):NOI 2011 兔兔与蛋蛋游戏

Description Input 输入的第一行包含两个正整数 n.m. 接下来 n行描述初始棋盘.其中第i 行包含 m个字符,每个字符都是大写英文字母"X".大写英文字母"O"或点号"."之一,分别表示对应的棋盘格中有黑色棋子.有白色棋子和没有棋子.其中点号"."恰好出现一次. 接下来一行包含一个整数 k(1≤k≤1000) ,表示兔兔和蛋蛋各进行了k次操作. 接下来 2k行描述一局游戏的过程.其中第 2i – 1行是兔兔的

[匈牙利算法][博弈] Luogu P1971 兔兔与蛋蛋

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

CQUOJ D. 会做题的兔兔

D. 会做题的兔兔 Time Limit: 2000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main Submit Status 大家都听说梅小姐喂养了很多兔兔.梅小姐的兔兔超级萌.超级听话,经常能帮助梅小姐AC题目. 有一天,梅小姐给兔兔们一个数字,然后命令兔兔们去寻找有多少个不同的集合满足集合内的元素相加等于这个数字,并且兔兔们找的每个数都只能是2的k次幂. 比如: 梅小姐给了

bzoj 2437: [Noi2011]兔兔与蛋蛋

Description Solution 考虑犯错误的条件:之前是处于必胜状态,该操作之后就变成了必败状态. 我们可以把这个过程看成两人对网格图进行黑白染色,变成了一个二分图模型,即当前位置向相邻不同颜色的位置连边,构成的二分图,一次游戏相当于一个最大匹配. 一个结论:如果一定存在包含当前位置的最大匹配,那么处于先手必胜状态 证明: 因为当前点不处于最大匹配中,那么只有非匹配边可以走,假设走到了\(v\),\(v\)点则可以走匹配边,假设走了一条匹配边,则到达的下一个点只能走非匹配边,因为匹配的

[bzoj2437]兔兔与蛋蛋

移动可以理解为空白格的移动,问题等价于双方在一张无向图(相邻不同色点连边,起点视为黑色)移动,不能经过重复的点,无法移动者为负由于这张图是二分图,因此有结论,先手必胜当且仅当起点一定在任意一组最大匹配中证明:必要性,即先手必胜=>一定在匹配中,其等价于不在匹配中=>后手必胜,考虑一组最大匹配,容易发现先手所走到的点一定在最大匹配中(否则匹配可以增大),而后手的策略就是一直走到那个点的匹配上,一定必胜充分性,即一定在匹配中=>先手必胜,那么当去掉起点后的最大匹配中,一定存在某一个点使得其可

【bzoj2432】【NOI2011】兔农

题目描述 农夫栋栋近年收入不景气,正在他发愁如何能多赚点钱时,他听到隔壁的小 朋友在讨论兔子繁殖的问题. 问题是这样的:第一个月初有一对刚出生的小兔子,经过两个月长大后,这 对兔子从第三个月开始,每个月初生一对小兔子.新出生的小兔子生长两个月后 又能每个月生出一对小兔子.问第 n 个月有多少只兔子? 聪明的你可能已经发现,第 n 个月的兔子数正好是第 n 个 Fibonacci(斐波那 契)数.栋栋不懂什么是 Fibonacci 数,但他也发现了规律:第 i+2 个月的兔子数 等于第 i 个月的