Gym100548H

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
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 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;iint 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;iint 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;iint 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;iint 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 #"<": ";
    if(dp[sx][sy][1]!=1) puts("Yes");
    else puts("No");
  }
  return 0;
}

你可能感兴趣的:(博弈论,dp)