当前位置:网站首页>【luogu P1971】兔兔与蛋蛋游戏(二分图博弈)
【luogu P1971】兔兔与蛋蛋游戏(二分图博弈)
2022-07-07 02:18:00 【SSL_TJH】
兔兔与蛋蛋游戏
题目链接:luogu P1971
题目大意
给你一个二维网格图,其中只有一个位置没有棋子,其它位置有白棋子或黑棋子。
然后两个人轮流操作,先手可以把空格子旁边四个中的白色棋子选一个移过来,后手则是移动黑色棋子。
然后无法移动者输,然后给你两个人的操作过程,保证后手赢,然后问你有那些时刻由原本先手必胜变成了先手必败。
思路
首先知道二分图博弈的话,你是可以发现这个可以是一个二分图博弈的模型。
(毕竟网格图嘛)
但是状态太多,那我们考虑优化,亦或是合并重复状态,去掉无用状态。
然后你在看两个人交替,而且每个人适用的情况是不同的,然后你又发现其实这个图不大。
那能不能把状态变成图点大小的级别的呢?思考一下会发现一个点不会别重复走。
因为你走出去再回来肯定是经过了偶数次,那这个时候就是另一个人操作来这个点,但是你上一个人走出去把自己的颜色留在了这里,下一个人是进不来的。
那有了这个性质,我们其实就不需要管别的位置的颜色了,只需要直接设状态是空格在什么位置。
然后连边是固定的因为你四周的颜色其实是固定的(得从一个不同颜色的走到这个颜色的,然后那个不同的颜色就相当于被替换成了这个颜色的)
所以就可以搞。
但是你这里不是一次询问,而是你可以理解为每次操作后都要求是否先手必胜(如果先手操作前和操作后这个局面都是先手必胜先手就失误了)。
那你跑那么多次网络流/匈牙利都不太行吧。
那我们考虑一次的时候我们是怎么弄的,我们是先弄删掉点的,然后再弄不删掉的。
那我们这个其实也可以倒序弄,先弄全部删掉的,然后一条一条加上,分别得到答案。
代码
#include<queue>
#include<cstdio>
#include<iostream>
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N = 45;
char s[N][N];
int n, m, K, tot, S, T;
bool col[N][N], in[N][N], win[2005];
int dx[4] = {
1, 0, -1, 0}, dy[4] = {
0, 1, 0, -1};
pair <int, int> del[2005];
int id(int x, int y) {
return (x - 1) * m + y;}
bool check(int x, int y) {
if (x < 1 || x > n) return 0; if (y < 1 || y > m) return 0; if (col[x][y]) return 0; return 1;}
bool check_(int x, int y) {
if (x < 1 || x > n) return 0; if (y < 1 || y > m) return 0; return 1;}
struct Flow {
struct node {
int x, to, nxt, op;
}e[N * N * 500];
int le[N * N], KK, dis[N * N], lee[N * N];
queue <int> q;
void add(int x, int y, int z) {
e[++KK] = (node){
z, y, le[x], KK + 1}; le[x] = KK;
e[++KK] = (node){
0, x, le[y], KK - 1}; le[y] = KK;
}
bool bfs() {
while (!q.empty()) q.pop();
for (int i = 1; i <= tot; i++) dis[i] = 0, lee[i] = le[i];
q.push(S); dis[S] = 1;
while (!q.empty()) {
int now = q.front(); q.pop();
for (int i = le[now]; i; i = e[i].nxt)
if (!dis[e[i].to] && e[i].x) {
dis[e[i].to] = dis[now] + 1;
if (e[i].to == T) return 1;
q.push(e[i].to);
}
}
return 0;
}
int dfs(int now, int sum) {
if (now == T) return sum;
int go = 0;
for (int &i = lee[now]; i; i = e[i].nxt)
if (dis[e[i].to] == dis[now] + 1 && e[i].x) {
int this_go = dfs(e[i].to, min(sum - go, e[i].x));
if (this_go) {
e[i].x -= this_go; e[e[i].op].x += this_go;
go += this_go; if (go == sum) return go;
}
}
return go;
}
int dinic() {
int re = 0;
while (bfs())
re += dfs(S, INF);
return re;
}
}W;
void Init() {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (col[i][j] && !in[i][j]) {
for (int k = 0; k < 4; k++) {
int tx = i + dx[k], ty = j + dy[k];
if (!check(tx, ty) || in[tx][ty]) continue;
W.add(id(i, j), id(tx, ty), 1);
}
}
W.dinic();
}
int main() {
scanf("%d %d", &n, &m); tot = id(n, m); S = ++tot; T = ++tot;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
s[i][j] = getchar(); while (s[i][j] != 'X' && s[i][j] != 'O' && s[i][j] != '.') s[i][j] = getchar();
if (s[i][j] == '.') del[0] = make_pair(i, j), in[i][j] = 1;
if (s[i][j] == '.' || s[i][j] == 'X') col[i][j] = 1, W.add(S, id(i, j), 1);
else W.add(id(i, j), T, 1);
}
scanf("%d", &K);
for (int i = 1; i <= K << 1; i++) {
int x, y; scanf("%d %d", &x, &y); del[i] = make_pair(x, y); in[x][y] = 1;
}
Init();
for (int i = K << 1; i >= 0; i--) {
pair <int, int> v = del[i];
in[v.first][v.second] = 0;
for (int j = 0; j < 4; j++) {
int tx = v.first + dx[j], ty = v.second + dy[j];
if (!check_(tx, ty) || in[tx][ty] || col[v.first][v.second] == col[tx][ty]) continue;
if (col[v.first][v.second]) W.add(id(v.first, v.second), id(tx, ty), 1);
else W.add(id(tx, ty), id(v.first, v.second), 1);
}
win[i] = W.dinic();
}
int ans = 0;
for (int i = 1; i <= K << 1; i += 2) {
if (win[i - 1] && win[i]) ans++;
}
printf("%d\n", ans);
for (int i = 1; i <= K << 1; i += 2) {
if (win[i - 1] && win[i]) {
printf("%d\n", (i + 1) / 2);
}
}
return 0;
}
边栏推荐
- Basic DOS commands
- Unity C# 函数笔记
- 中英文说明书丨ProSci LAG-3 重组蛋白
- Etcd database source code analysis -- starting from the start function of raftnode
- Implementation of VGA protocol based on FPGA
- Can't you really do it when you are 35 years old?
- Linear algebra (1)
- JWT certification
- 安装VMmare时候提示hyper-v / device defender 侧通道安全性
- Tkinter window selects PCD file and displays point cloud (open3d)
猜你喜欢
博士申请 | 上海交通大学自然科学研究院洪亮教授招收深度学习方向博士生
安装VMmare时候提示hyper-v / device defender 侧通道安全性
雷特智能家居龙海祁:从专业调光到全宅智能,20年专注成就专业
港科大&MSRA新研究:关于图像到图像转换,Fine-tuning is all you need
Markdown displays pictures side by side
Common problems of caching in high concurrency scenarios
「解析」FocalLoss 解决数据不平衡问题
Force deduction 62 different paths (the number of all paths from the upper left to the lower right of the matrix) (dynamic planning)
学术报告系列(六) - Autonomous Driving on the journey to full autonomy
Redis(二)—Redis通用命令
随机推荐
一段程序让你明白什么静态内部类,局部内部类,匿名内部类
Learning notes | data Xiaobai uses dataease to make a large data screen
中英文说明书丨ProSci LAG-3 重组蛋白
Problems and precautions about using data pumps (expdp, impdp) to export and import large capacity tables in Oracle migration
如何解决数据库插入数据显示SQLSTATE[HY000]: General error: 1364 Field ‘xxxxx‘ doesn‘t have a default value错误
雷特智能家居龙海祁:从专业调光到全宅智能,20年专注成就专业
安装VMmare时候提示hyper-v / device defender 侧通道安全性
UIC(组态UI工程)公版文件库新增7款行业素材
程序员的日常 | 每日趣闻
VMware安装后打开就蓝屏
UIC (configuration UI Engineering) public file library adds 7 industry materials
Google Chrome browser released patch 103.0.5060.114 to fix the 0-day vulnerability
Audio distortion analysis of DSP and DAC based on adau1452
LM小型可编程控制器软件(基于CoDeSys)笔记二十三:伺服电机运行(步进电机)相对坐标转换为绝对坐标
FlexRay通信协议概述
2022 Android interview essential knowledge points, a comprehensive summary
偏执的非合格公司
ICML 2022 | 探索语言模型的最佳架构和训练方法
Leite smart home longhaiqi: from professional dimming to full house intelligence, 20 years of focus on professional achievements
Test the foundation of development, and teach you to prepare for a fully functional web platform environment