SGU 520 Fire in the Country 博弈SG函数(或者YY一下)
来源:互联网 发布:最新版学越南语软件 编辑:程序博客网 时间:2024/05/17 06:47
题目大意:
现在给出一个有着n个顶点m条边的图,边为双向边, 现在两个人轮流操作机器人,机器人从点1开始走,两个人轮流控制机器人走向与当前点相连的点,两个人每次操作机器人走的同时,火势将会向外蔓延,每操作一次之后火势就向与当前着火点相连的点蔓延,机器人在谁操作之后被火烧到谁就输,比如样例:
Nikolay先手从1走到3,当天晚上1着火,然后Vladimir只能从3走到1,当天晚上1是着火点所以Vladimir输了,输出Vladimir
大致思路:
这题比赛的时候想的是一个YY的做法:
我定义P点:一个点是P点当且仅当谁控制机器人走到这个点谁就赢
相反的是N点:一个点是N点表示谁控制机器人走到这个点谁就输
由于火势是不停蔓延的,那么控制机器人行动时不能回头,这样即使图中有环,也不可能往回走,可以先BFS遍历一下找到点的层级( 即到达该点的步数 ) 这样我们就只能控制机器人从层级低的点走到层级高的点,这样原图可以变成一个无环有向图,图的边来自于原图中层级低的点指向层级高的点且在原图中连通
我们考虑父亲结点root和子节点son[ i ] ( 这里就是拓扑序的意思,方编写我就当做树的层级吧..虽然可能不是树...) ,当父亲节点没有子节点时,一定是 P 点,因为下一个人已经无路可走了
当父亲节点有子节点时,如果子节点中有P点,那么父亲节点是N点( 博弈中的小策略 )也很容易明白因为代打这个父亲节点后,下一个人一定会选择走到P点这样走到这个父亲节点的人就输了,也就是说只需要判断父亲节点的子节点中有无P点即可判断父亲节点是P点还是N点
这样dfs一下找到节点1的值是P还是N即可,是N则Vladimir赔钱,否则Nikolay赔钱
比赛之后学了一些图上的博弈,发现这题可以用Sprague-Grundy函数来解和之前一样BFS建好新的无环有向图之后,用dfs迭代求SG函数的值
当SG[ 1 ] == 0 时,Nikolay赔钱,SG[ 1 ] != 0时,Vladimir赔钱
这里附上SG函数解法的代码(相比上一种比赛时YY出来的方案感觉还是好一点)
题解写一半发现CSDN维护了..我擦...
Result : Accepted Memory : 322 KB Time : 15 ms
/* * Author: Gatevin * Created Time: 2014/9/2 22:10:56 * File Name: C.cpp */#include<iostream>#include<sstream>#include<fstream>#include<vector>#include<list>#include<deque>#include<queue>#include<stack>#include<map>#include<set>#include<bitset>#include<algorithm>#include<cstdio>#include<cstdlib>#include<cstring>#include<cctype>#include<cmath>#include<ctime>#include<iomanip>using namespace std;const double eps(1e-8);typedef long long lint;#define pb(x) push_back(x)#define clr(x) memset(x, 0, sizeof(x))int n,m;int deep[1010];//到达对应的点需要走的步数bool vis[1010];//用了两次,都是用来记忆化vector <int> G[1010];//原图vector <int> F[1010];//删边之后的博弈求SG函数用图queue <int> q;int SG[1010];void bfs(){ clr(vis); vis[1] = 1; q.push(1); while(!q.empty()) { for(unsigned int i = 0; i < G[q.front()].size(); i++) { if(!vis[G[q.front()][i]]) { deep[G[q.front()][i]] = deep[q.front()] + 1; vis[G[q.front()][i]] = 1; q.push(G[q.front()][i]); } } q.pop(); } return;}void build(){ for(int i = 1; i <= n; i++) { for(unsigned int j = 0; j < G[i].size(); j++) { if(deep[i] < deep[G[i][j]]) { F[i].pb(G[i][j]); } } } return;}bool check(int val, int root)//求mex(){ for(unsigned int i = 0; i < F[root].size(); i++) { if(val == SG[F[root][i]]) return true; } return false;}void dfs(int root)//递归求解SG函数{ if(F[root].empty()) { SG[root] = 0; return; } if(vis[root]) return; for(unsigned int i = 0; i < F[root].size(); i++) { dfs(F[root][i]); } int cnt = 0; while(check(cnt, root)) { cnt++; } SG[root] = cnt; vis[root] = 1; return;}int main(){ scanf("%d %d", &n, &m); int tx,ty; for(int i = 1; i <= m; i++) { scanf("%d %d", &tx, &ty); G[tx].pb(ty); G[ty].pb(tx); } bfs(); build(); clr(vis); dfs(1); if(SG[1] != 0) { printf("Vladimir\n"); } else { printf("Nikolay\n"); } return 0;}
- SGU 520 Fire in the Country 博弈SG函数(或者YY一下)
- sgu - 520 - Fire in the Country(bfs + dfs + 博弈)
- Gym 101246DFire in the Country (dfs暴力博弈)
- 2010-2011 ACM-ICPC, NEERC, Southern Subregional Contest Fire in the Country(博弈论+搜索)
- SG函数 博弈
- 博弈之sg函数
- 博弈のSG函数
- hoj1848 Sg函数博弈
- 博弈sg函数
- 博弈SG函数
- 博弈sg函数
- 博弈通解:SG函数
- 博弈 SG函数
- sg函数 和 博弈
- 博弈sg函数模板
- 博弈之SG函数
- Good Luck in CET-4 Everybody! + 博弈 + sg函数
- 博弈函数与sg函数
- 读了借来的《牧羊少年的奇幻之旅》
- 第十二章 12.1.1节练习
- rule.mk
- 关于wampserver 局域网访问问题
- iOS SVN的使用
- SGU 520 Fire in the Country 博弈SG函数(或者YY一下)
- vim常用快捷键
- 多线程安全
- pyInstaller
- SVM模型预测
- TCP/IP详解--TCP/IP可靠的原理 滑动窗口 拥塞窗口
- poj2299 Ultra-QuickSort&&NYOJ117 求逆序数 (树状数组求逆序对数+离散化)+(归并排序)
- Longest Substring Without Repeating Characters
- R相关分析