题面

题面

题解

通过观察,我们可以发现如下性质:

  • 可以看做是2个人在不断移动空格,只是2个人能移动的边不同
  • 一个位置不会被重复经过 : 根据题目要求,因为是按黑白轮流走,所以不可能重复经过一个点,不然就变成一个人连续走2次了
  • 原图是一个二分图 : 也是由按黑白轮流走这个要求得到的

    因此我们对原图按照与原点的距离进行黑白染色,再跑二分图博弈即可。
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 45
#define ac 5000 int n, m, sx, sy, all;
int id[AC][AC], ans[ac], link[ac];
int a[6] = {-1, 1, 0, 0}, b[6] = {0, 0, -1, 1};
bool can[AC][AC], z[ac], vis[ac];
char s[AC][AC]; struct node{int x, y;}back[ac]; inline int read()
{
int x = 0;char c = getchar();
while(c > '9' || c < '0') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x;
} bool check(int x, int y)//起点是黑色
{
int tmp = abs(x - sx) + abs(y - sy);
if((tmp & 1) && s[x][y] == 'O') return 1;//相距奇数格,则为白格,需要白色
else if(!(tmp & 1) && s[x][y] == 'X') return 1;
else if(s[x][y] == '.') return 1;
return 0;
} bool dfs(int x)
{
for(R i = 0; i < 4; i ++)
{
int xx = back[x].x + a[i], yy = back[x].y + b[i], ID = id[xx][yy];
if(xx <= 0 || yy <= 0 || xx > n || yy > m) continue;
if(!can[xx][yy] || vis[ID]) continue;
vis[ID] = true;
if(!link[ID] || dfs(link[ID]))
{
link[ID] = x, link[x] = ID;
return true;
}
}
return false;
} void cal()
{
int tmp = (sx + sy) % 2;
for(R i = 1; i <= all; i ++)
{
int x = back[i].x, y = back[i].y;
if((x + y) % 2 != tmp || !can[x][y]) continue;//和为奇数则在T集合
memset(vis, 0, sizeof(vis)), dfs(i);
}
} bool dfs1(int x)
{
for(R i = 0; i < 4; i ++)
{
int xx = back[x].x + a[i], yy = back[x].y + b[i], ID = id[xx][yy];
if(xx <= 0 || yy <= 0 || xx > n || yy > m) continue;
if(!can[xx][yy] || vis[ID]) continue;
vis[ID] = true;
if(!link[ID] || dfs(link[ID])) return true;
}
return false;
} void pre()
{
n = read(), m = read(), all = n * m;
int tmp1 = 1, tmp2 = 2;
for(R i = 1; i <= n; i ++)
{
scanf("%s", s[i] + 1);
for(R j = 1; j <= m; j ++)
{
if(s[i][j] == '.') sx = i, sy = j;
if((i + j) & 1) id[i][j] = tmp2, back[tmp2] = (node){i, j}, tmp2 += 2;
else id[i][j] = tmp1, back[tmp1] = (node){i, j}, tmp1 += 2;
}
}
for(R i = 1; i <= n; i ++)
for(R j = 1; j <= m; j ++) can[i][j] = check(i, j);
} void check_()
{
for(int i = 1; i <= n; i ++)
{
for(int j = 1; j <= m; j ++) printf("%d ", can[i][j]);
printf("\n");
} for(R i = 1; i <= n; i ++)
{
for(R j = 1; j <= m; j ++) printf("%d ", link[id[i][j]]);
printf("\n");
}
} void work()
{
int T = read() << 1, x, y, ID, tmp; bool done;
for(R i = 0; i <= T; i ++)
{
for(R j = 1; j <= all; j ++) z[j] = 0;
if(i) x = read(), y = read(), ID = id[x][y];
else x = sx, y = sy, ID = id[x][y];
can[x][y] = 0;//这个要在一开始就修改
if(!link[ID]) continue;//搜S/T集合中有没有可到达的同侧未匹配点来取代它,因为直接搜不太方便,所以直接搜对面的匹配点是否可以找到增广路
memset(vis, 0, sizeof(vis));
done = dfs(link[ID]);//找到了说明这个点不是必须点
tmp = link[ID];//所以搜这个点的匹配点是否可以找到对面的一个未匹配点(反向增广)
if(done) link[ID] = 0;//清空这个点的匹配,因为这个点已经到过了,所以就不能到达了,如果已经匹配上了就不能改了
else if(!done) link[ID] = link[tmp] = 0, ans[i] = true;//没有可取代点就先手必胜
}
/*for(R i = 0; i <= T; i ++) printf("%d ", ans[i]);
printf("\n");*/
int rnt = 0;
for(R i = 0; i <= T; i += 2)
if(ans[i] == 1 && ans[i + 1] == 1) ++ rnt;
printf("%d\n", rnt);
for(R i = 0; i <= T; i += 2)
if(ans[i] == 1 && ans[i + 1] == 1) printf("%d\n", (i + 2) >> 1);
} int main()
{
// freopen("in.in", "r", stdin);
pre();
cal();
work();
// fclose(stdin);
return 0;
}

[NOI2011]兔兔与蛋蛋游戏 二分图博弈的更多相关文章

  1. [luogu1971 NOI2011] 兔兔与蛋蛋游戏 (二分图博弈)

    传送门 Solution 补一篇二分图博弈 这个博客写的很详细qwq: https://www.cnblogs.com/maijing/p/4703094.html Code //By Menteur ...

  2. BZOJ.2437.[NOI2011]兔兔与蛋蛋游戏(二分图博弈 匈牙利)

    题目链接 首先空格的移动等价于棋子在黑白格交替移动(设起点移向白格就是黑色),且不会走到到起点距离为奇数的黑格.到起点距离为偶数的白格(删掉就行了),且不会重复走一个格子. (然后策略就同上题了,只不 ...

  3. [JSOI2009]游戏 二分图博弈

    题面 题面 题解 二分图博弈的模板题,只要会二分图博弈就可以做了,可以当做板子打. 根据二分图博弈,如果一个点x在某种方案中不属于最大匹配,那么这是一个先手必败点. 因为对方先手,因此我们就是要找这样 ...

  4. BZOJ 1443 游戏(二分图博弈)

    新知识get. 一类博弈问题,基于以下条件: 1.博弈者人数为两人,双方轮流进行决策.2.博弈状态(对应点)可分为两类(状态空间可分为两个集合),对应二分图两边(X集和Y集).任意合法的决策(对应边) ...

  5. luogu4055 游戏 (二分图博弈)

    考虑对非障碍的点黑白染色然后做二分图最大匹配,那么有结论,先手必胜当且仅当不是完美匹配,而且可以放的点是那些可以不匹配的点 从非匹配点开始走,后手只能走到匹配点,于是先手就可以走匹配边.由于不能走走过 ...

  6. [模板] 二分图博弈 && BZOJ2463:[中山市选2009]谁能赢呢?

    二分图博弈 from BZOJ 1443 游戏(二分图博弈) - free-loop - 博客园 定义 1.博弈者人数为两人,双方轮流进行决策. 2.博弈状态(对应点)可分为两类(状态空间可分为两个集 ...

  7. 【BZOJ 2437】 2437: [Noi2011]兔兔与蛋蛋 (博弈+二分图匹配**)

    未经博主同意不得转载 2437: [Noi2011]兔兔与蛋蛋 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 693  Solved: 442 Des ...

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

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

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

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

随机推荐

  1. [css 实践篇]CSS中的尺寸单位

    绝对单位 px: Pixel 像素 pt: Points 磅 pc: Picas 派卡 in: Inches 英寸 mm: Millimeter 毫米 cm: Centimeter 厘米 q: Qua ...

  2. C# VS,连接到oracle 报要升级到8.多少版本的错

    1:确定服务器的oracle版本 2:本地的客户端版本要和服务器一致 3:操作系统位数要一致

  3. 我们一起学习WCF 第八篇回调函数

    什么是回调函数? 一个简单的例子:小明想要在京东购买一件商品.他会登陆网站选好自己的商品.然后他把这件商品放在购物车,然后开始付钱(这个表示触发,不付钱不发货(排除货到付款)).然后京东的人员收到了小 ...

  4. 搜索引擎ElasticSearch系列(四): ElasticSearch2.4.4 sql插件安装

    一:ElasticSearch sql插件简介 With this plugin you can query elasticsearch using familiar SQL syntax. You ...

  5. Windows网络通信(二):socket异步编程

    简述 这里使用的API和同步编程的API是差不多的,只多了一个ioctlsocket和select函数.这里面涉及一个很重要的结构体fd_set.这里用到的API大部分都是windows和linux通 ...

  6. hadoop 基础入门

    启动:   格式化节点:bin/hdfs namenode -format   全部启动:sbin/start-dfs:datanode.namenode                    sbi ...

  7. mongo复杂操作

    相比关系型数据库, Array [1,2,3,4,5] 和 Object { 'name':'DragonFire' } 是MongoDB 比较特殊的类型了 特殊在哪里呢?在他们的操作上又有什么需要注 ...

  8. Nginx之一:Nginx的编译安装

    一.Nginx简介 官方网址:http://nginx.org/ Nginx是由1994年毕业于俄罗斯国立莫斯科鲍曼科技大学的同学为俄罗斯rambler.ru公司开发的,开发工作最早从2002年开始, ...

  9. spark读取外部配置文件的方法

    spark读取外部配置文件的方法 spark-submit  --files /tmp/fileName /tmp/test.jar 使用spark提交时使用--files参数,spark会将将本地的 ...

  10. SST:Single-Stream Temporal Action Proposals论文笔记

    SST:Single-Stream Temporal Action Proposals 这是本仙女认认真真读完且把算法全部读懂(其实也不是非常懂)的第一篇论文 CVPR2017 一作 论文写作的动机m ...