Gym100548H
来源:互联网 发布:淘宝网家纺四件套 编辑:程序博客网 时间:2024/06/06 18:57
2014西安赛区的H,是一道有向图上的博弈问题
首先我们要确定一下结束状态,一种是两点重合,还有一种是没法移动棋子
接下来我们把结束状态放在队列的队首,倒退之前的状态
我用1表示Alice必胜,2表示Bob必胜,3表示平局,分了4种情况
1、轮到Bob,状态为1,dp[x][y][1]=1,那么之前能到达y的点dp[x][v][0]=1
2、轮到Alice,状态为2,dp[x][y][0]=2,那么x的入度v,dp[v][y][1]=2
3、轮到Bob,状态为2,那么对于y的入度v,vis[x][v][y][0]=1,v不能移动到y
4、轮到Alice,状态为1,与3的情况类似
#include<bits/stdc++.h>using namespace std;const int maxn=100+10;struct node{ int x,y,st;};int dp[maxn][maxn][2],n,m,T,cnt[maxn][maxn][2];bool vis[maxn][maxn][maxn][2];queue<node> Q;vector<int> g[maxn];vector<int> h[maxn];void work(){ while(!Q.empty()) { node x=Q.front();Q.pop(); if(x.st==1&&dp[x.x][x.y][x.st]==1) { for(int i=0;i<h[x.y].size();i++) { int v=h[x.y][i]; if(!dp[x.x][v][0]) { dp[x.x][v][0]=1; Q.push((node){x.x,v,0}); } } } else if(x.st==0&&dp[x.x][x.y][x.st]==2) { for(int i=0;i<h[x.x].size();i++) { int v=h[x.x][i]; if(!dp[v][x.y][1]) { dp[v][x.y][1]=2; Q.push((node){v,x.y,1}); } } } else if(x.st==0&&dp[x.x][x.y][x.st]==1) { for(int i=0;i<h[x.x].size();i++) { int v=h[x.x][i]; if(!vis[v][x.y][x.x][1]) { vis[v][x.y][x.x][1]=1;cnt[v][x.y][1]++; if(cnt[v][x.y][1]==g[v].size()&&!dp[v][x.y][1]) { dp[v][x.y][1]=1; Q.push((node){v,x.y,1}); } } } } else if(x.st==1&&dp[x.x][x.y][x.st]==2) { for(int i=0;i<h[x.y].size();i++) { int v=h[x.y][i]; if(!vis[x.x][v][x.y][0]) { vis[x.x][v][x.y][0]=1;cnt[x.x][v][0]++; if(cnt[x.x][v][0]==g[v].size()&&!dp[x.x][v][0]) { dp[x.x][v][0]=2; Q.push((node){x.x,v,0}); } } } } }}int main(){ //freopen("test.in","r",stdin); scanf("%d",&T); for(int tt=1;tt<=T;tt++) { scanf("%d%d",&n,&m); memset(dp,0,sizeof(dp));memset(vis,0,sizeof(vis)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;i++) { h[i].clear();g[i].clear(); dp[i][i][0]=dp[i][i][1]=1; Q.push((node){i,i,0});Q.push((node){i,i,1}); } for(int i=1;i<=m;i++) { int u,v;scanf("%d%d",&u,&v); h[v].push_back(u); g[u].push_back(v); } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j) { if(!g[i].size()) dp[i][j][1]=1;Q.push((node){i,j,1}); if(!g[j].size()) dp[i][j][0]=2;Q.push((node){i,j,0}); } work(); int sx,sy;scanf("%d%d",&sx,&sy); cout<<"Case #"<<tt<<": "; if(dp[sx][sy][1]!=1) puts("Yes"); else puts("No"); } return 0;}
0 0
- Gym100548H
- 508. Most Frequent Subtree Sum
- 16年轻院赛后总结
- 算法导论第六章之最大、最小堆
- lintcode——二叉树的最小深度
- 控制器跳转和视图切换之NavigationController,UITabBarController,模态
- Gym100548H
- JavaScript深入之从原型到原型链
- excel文本提取
- -bash: pod: command not found
- Python 实现共现矩阵算法
- linux 安装g++等工具
- 递归如何转换为非递归
- Code::Blocks error: range-based 'for' loops are not allowed in C++98 mode
- C的隐式类型转换