当前位置:网站首页>【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;
}
边栏推荐
- docker-compose启动redis集群
- Jmeter 5.5版本发布说明
- Cloudcompare point pair selection
- Unable to debug screen program with serial port
- MySQL installation
- 360 Zhiyu released 7.0 new products to create an exclusive "unified digital workspace" for the party, government and army, and central and state-owned enterprises
- Learning notes | data Xiaobai uses dataease to make a large data screen
- Prompt for channel security on the super-v / device defender side when installing vmmare
- ICML 2022 | explore the best architecture and training method of language model
- Experience sharing of contribution of "management world"
猜你喜欢
String (explanation)
学习笔记|数据小白使用DataEase制作数据大屏
uniapp开发小程序如何使用微信云托管或云函数进行云开发
二十岁的我4面拿到字节跳动offer,至今不敢相信
A program lets you understand what static inner classes, local inner classes, and anonymous inner classes are
Can't you really do it when you are 35 years old?
FlexRay通信协议概述
2022 Android interview essential knowledge points, a comprehensive summary
How to use wechat cloud hosting or cloud functions for cloud development of unapp development applet
循环肿瘤细胞——Abnova 解决方案来啦
随机推荐
JESD204B时钟网络
ip地址那点事
2022 Android interview essential knowledge points, a comprehensive summary
学习笔记|数据小白使用DataEase制作数据大屏
Tkinter window selects PCD file and displays point cloud (open3d)
循环肿瘤细胞——Abnova 解决方案来啦
Doctoral application | Professor Hong Liang, Academy of natural sciences, Shanghai Jiaotong University, enrolls doctoral students in deep learning
Shared memory for interprocess communication
ICML 2022 | 探索语言模型的最佳架构和训练方法
Ha Qu projection dark horse posture, only half a year to break through the 1000 yuan projector market!
String (explanation)
UIC(组态UI工程)公版文件库新增7款行业素材
C interview encryption program: input plaintext by keyboard, convert it into ciphertext through encryption program and output it to the screen.
港科大&MSRA新研究:关于图像到图像转换,Fine-tuning is all you need
Party A's requirements for those who have lost 800 yuan
「解析」FocalLoss 解决数据不平衡问题
"Parse" focalloss to solve the problem of data imbalance
Jmeter 5.5版本发布说明
Performance comparison between Ceres solver and g2o
K8s running Oracle