Codeforces Round #406 (Div. 2) C 博弈
来源:互联网 发布:吉利电动车知豆d2价钱 编辑:程序博客网 时间:2024/06/10 05:28
题目链接
此题类似于当初上ACM公选课博弈一节的某例题,考察了对于必胜点,必败点等基础知识的掌握。
对于此题:
必败点(P点) :前一个选手(Previous player)将取胜的位置称为必败点。
必胜点(N点) :下一个选手(Next player)将取胜的位置称为必胜点。
对于必败点和必胜点,分别有以下性质:
必败点:无论怎么操作,从必败点下一步都只能进入必胜点。
必胜点:至少存在一种操作,能从必胜点走到必败点。
上述概念看似有点抽象,对于本题,简单理解就是:
当轮到某玩家操作时,无论怎么操作,操作结束后都是对方胜利,此时就是必败点。考虑特殊例子的话,当棋子已经走到了 1 的点,游戏已经结束,这时对于下一个操作的人此时就是必败点。
而如果轮到某玩家操作时,他有多种不同的操作选择,但存在一种操作使得他选择后,对方无论怎么操作都是输,即使对方进入必败点,则该玩家此时处于必胜点。
所以对于本题,我们可以考虑在时间轴上从后往前BFS,因为游戏结束有着明确的规定,即棋子移动到了 1 的点。若棋子已经在 1 的点,则谁先手谁就已经输了(因为在先手操作前棋子已经到达1,则说明是后手达到胜利条件)。
以 1 作为必败点,从后往前搜索,则存在两种情况:
(1).当前状态为必败点。
则上一个状态必为必胜点。(如果某一个状态通过某一个操作能走到必败点,则该点一定是必胜点)
(2).当前状态为必胜点。
此时情况便复杂一点,因为此时有两种可能:
必胜点 --> 必胜点必败点 --> 必胜点
故我们可以用一个数组保存某个点到达必胜点的次数,若能够达到必胜点的次数等于总的操作数,即无论怎么操作,都只能从当前状态到达必胜点。
则当前状态为必败点。
则便是我下面代码里面的出度数组: deg[]
因为总的操作数是 k1 / k2,故我们可以提前预处理deg数组为总的操作数,一旦能够到达某一个必胜点,则出度减一,当出度为0时,则达到了上述条件。
然后没有更新答案的点就是可以为圈的点。
代码:
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int INF = 1e9 + 7;const int A = 1e4 + 100;class P{public: int pos,k; P(int i,int j):pos(i),k(j){}};int val_1[A],val_2[A];int deg_1[A],deg_2[A];int ans_1[A],ans_2[A]; // 1 必败 2 必胜queue<P> que;int main(){ int n; scanf("%d",&n); int k1,k2; scanf("%d",&k1); for(int i=1 ;i<=k1 ;i++) scanf("%d",&val_1[i]); scanf("%d",&k2); for(int i=1 ;i<=k2 ;i++) scanf("%d",&val_2[i]); ans_1[1] = ans_2[1] = 1; que.push(P(1,1)),que.push(P(1,2)); for(int i=1 ;i<=n ;i++){ deg_1[i] = k1; deg_2[i] = k2; } deg_1[1] = deg_2[1] = INF; while(que.size()){ P now = que.front();que.pop(); if(now.k == 1){ for(int i=1 ;i<=k2 ;i++){ int ne = (now.pos - val_2[i] - 1 + n) % n + 1; //避免产生0 if(ans_2[ne]) continue; if(ans_1[now.pos] == 1){ ans_2[ne] = 2; que.push(P(ne,2)); } else{ deg_2[ne]--; if(deg_2[ne] == 0){ ans_2[ne] = 1; que.push(P(ne,2)); } } } } else{ for(int i=1 ;i<=k1 ;i++){ int ne = (now.pos - val_1[i] - 1 + n) % n + 1; if(ans_1[ne]) continue; if(ans_2[now.pos] == 1){ ans_1[ne] = 2; que.push(P(ne,1)); } else{ deg_1[ne]--; if(deg_1[ne] == 0){ ans_1[ne] = 1; que.push(P(ne,1)); } } } } } for(int i=2 ;i<=n ;i++){ if(ans_1[i] == 2) printf("Win "); else if(ans_1[i] == 1) printf("Lose "); else printf("Loop "); } puts(""); for(int i=2 ;i<=n ;i++){ if(ans_2[i] == 2) printf("Win "); else if(ans_2[i] == 1) printf("Lose "); else printf("Loop "); } return 0;}
- Codeforces Round #406 (Div. 2) C 博弈
- Codeforces Round #406 (Div. 2):C. Berzerk(记忆化搜索解决博弈问题)
- Codeforces Round #406 (Div. 2) C. Berzerk(有向图博弈)
- Codeforces Round #330 (Div. 2)C. Warrior and Archer(博弈,贪心)
- Codeforces Round #330 (Div. 2) C. Warrior and Archer(贪心博弈)
- Codeforces Round #366 (Div. 2) A 【水题】& B【博弈】 & C 【思维】
- Codeforces Round #330 (Div. 2)C. Warrior and Archer【博弈+逆向思维】
- Codeforces Round #330 (Div. 2)C. Warrior and Archer(博弈)
- 【codeforces】Codeforces Round #370 (Div. 2) C
- Codeforces Round #124 (Div. 2) A. Plate Game(博弈)
- Codeforces Round #429(Div.2) B Godsend 博弈
- Codeforces Round #432 (Div. 2) (Codeforces 850C) E. Arpa and a game with Mojtaba 博弈+状态压缩
- Codeforces Round #406 (Div. 2)
- Codeforces Round #406 (Div. 2)
- Codeforces Round #406 (Div. 2)
- Codeforces Round #406 (Div. 2)
- Codeforces Round #406 (Div. 2)
- Codeforces Round #105 (Div. 2) C
- 关于解决Eclipse报错“Path must include project and resource name:xxx.xxx”的方式
- 二分贪心 T
- Tomcat无法打开阿帕奇主页404错误、搭建文件服务器问题解决方法
- 数据分析2017系统系统设计架构师的通过人数与通过率
- mac如何设置NDK路径
- Codeforces Round #406 (Div. 2) C 博弈
- 复习之路
- 超简单BeautifulSoup版Csdn博客(摘要视图)爬虫
- 1102. Invert a Binary Tree 解析
- 分类:情感分析
- Android数据安全之AES加密
- Android线程和线程池
- 推荐系统学习(一)——推荐引擎初探
- 数据结构之图的邻接表的基本操作