1. 程式人生 > 程式設計 >C++實現塗色遊戲(博弈)

C++實現塗色遊戲(博弈)

在一個2*N的格子上,Alice和Bob又開始了新遊戲之旅。

這些格子中的一些已經被塗過色,Alice和Bob輪流在這些格子裡進行塗色操作,使用兩種塗色工具,第一種可以塗色任意一個格子,第二種可以塗色任意一個2*2的格子。每一輪遊戲裡,他們可以選擇一種工具來塗色尚未被染色的格子。需要注意,塗色2*2的格子時,4個格子都應當未被塗色。最後一步塗滿所有格子的玩家獲勝。

一如既往,Alice先手,最優策略,誰是贏家?
Input輸入第一行為T,表示有T組測試資料。
每組資料包含兩個數字,N與M,M表示有多少個已被染色的格子。接下來的M行每行有兩個數字Xi與Yi,表示已經被塗色的格子座標。

[Technical Specification]

1. 1 <= T <= 74
2. 1 <= N <= 4747
3. 0 <= M <= 2 * N
4. 1 <= Xi <= 2,1 <= Yi <= N,格子座標不會重複出現
Output對每組資料,先輸出為第幾組資料,然後輸出“Alice”或者“Bob”,表示這輪遊戲的贏家。 Sample Input
2
2 0
2 2
1 1
2 2
Sample Output
Case 1: Alice
Case 2: Bob

思路:

可以先考慮有連續n列的空格的sg值是多少。

n=0時顯然sg[0]=0,之後就是普通的sg函式打表,只不過是要將格子分割槽而已。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <queue>
#include <algorithm>
#include <vector>
#include <stack>
#define INF 0x3f3f3f3f
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;
const int maxn=5000;
int sg[maxn];
bool pl[2][maxn];
int get_sg(int x)
{
 if(sg[x]!=-1)
  return sg[x];
 bool vis[maxn];
 memset(vis,false,sizeof(vis));
 for(int i=0; i<=x-1-i; i++)
 {
  int t=get_sg(i)^1^get_sg(x-1-i); //只塗這一列的其中一個格子
  vis[t]=true;
 }
 for(int i=0; i<=x-2-i; i++)
 {
  int t=get_sg(i)^get_sg(x-i-2); //這一列的格子都塗
  vis[t]=true;
 }
 for(int i=0; ; i++)
 {
  if(!vis[i])
  {
   sg[x]=i;
   break;
  }
 }
 return sg[x];
}
int main()
{
 memset(sg,-1,sizeof(sg));
 sg[0]=0;
 for(int i=1; i<maxn; i++)
  sg[i]=get_sg(i);
 int t;
 scanf("%d",&t);
 for(int cas=1; cas<=t; cas++)
 {
  int n,m;
  scanf("%d%d",&n,&m);
  memset(pl,sizeof(pl));
  int ans=0;
  for(int i=1; i<=m; i++)
  {
   int x,y;
   scanf("%d%d",&x,&y);
   pl[--x][--y]=true; 
  }
  int cnt=0;
  for(int i=0; i<n; i++) //將格子分割槽
  {
   if(pl[0][i]&&pl[1][i])  //如果某一列的格子都塗了,那麼異或這一列格子之前的連續空格子的sg值
   {
    ans^=sg[cnt];
    cnt=0;
    continue;
   }
   if(pl[0][i]^pl[1][i]) //如果這一列之塗了一個格子,那麼異或這一列格子之前的連續空格子的sg值再異或1
   {
    ans=ans^sg[cnt]^1;
    cnt=0;
    continue;
   }
   cnt++;  //如果這一列沒有格子被塗,那麼連續空格子的長度+1
  }
  ans^=sg[cnt];
  if(ans)
   printf("Case %d: Alice\n",cas);
  else
   printf("Case %d: Bob\n",cas);
 }
 return 0;
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。