MemSQL start[c]up Round 2 - online version C. More Reclamation(博弈)

 

題目大意

 

額,寫來寫去,我仍是直接說抽象以後的題目大意吧:ios

有一個 r*2 的矩形,兩我的輪流的在矩形上面減去一個 1*1 的小正方形,要求在減的過程當中,不能使矩形「斷開」,也就是說,若是一我的減去了 (i, 1) 這個矩形,那麼,(i-1, 2), (i+1, 2), (i, 2) 這三個小正方形不能再被減去了,由於一旦減去它們中的一個,整個矩形就會被「剪斷」ide

如今給你一個 r 和 n (1 r ≤ 100, 0 nr),表示有一個 r*2 矩形,已經有了 n 個位置被減去了,再給 n 個位置的座標,題目保證開始的狀態矩形不會被剪斷.函數

如今問,對於當前的狀態,先手是否必勝spa

 

作法分析

 

這題是博弈已經沒得說了,並且,很明顯是遊戲的和的問題,必然是爆 sg 函數了code

先來看看怎麼表示狀態:sg[len][x][y] 表示,有一個長度爲 len 的矩形,它的 len*2 個小正方形都在,最左邊的一個小正方形只能按照 x 的方式剪掉,最右邊的一個小正方形只能按照 y 的方式剪掉,其中:x=1 或者 y=1 表示剪掉的是第一排的矩形,x=2 或者 y=2 表示剪掉的是第二的矩形,x=0 或者 y=0 表示沒有限制,即:能夠剪掉第一的也能夠剪掉第二blog

那麼,當 len=0 的時候,必然有 sg[0][x][y]=0,其中 0x2, 0y2遊戲

當 len=1 的時候,必然有 sg[1][1][2]=sg[1][2][1]=0, sg[1][1][1]=sg[1][2][2]=sg[1][0][x]=sg[1][x][0]=1,其中 0x2get

根據狀態的定義,當前狀態的下一個子狀態也很好肯定,先記憶化搜索將 sg 函數暴力出來string

而後,根據輸入的矩形,將舉行分解成若干個子矩形,每一個子矩形都應該儘可能大,這樣,每一個子矩形必然屬於上面提到的的一個狀態之一it

如今的遊戲就變成了不少個遊戲的和了,求出這些子游戲的 sg 值的異或和 sum,若是 sum!=0,先手必勝,不然先手必敗

 

參考代碼

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 #include <algorithm>
 6 
 7 using namespace std;
 8 
 9 const int N=105;
10 
11 int sg[N][3][3];
12 struct data {
13     int id, val;
14     bool operator < (const data &T) const {
15         return id<T.id;
16     }
17 } A[N];
18 
19 int GET_SG(int len, int x, int y) {
20     if(sg[len][x][y]!=-1) return sg[len][x][y];
21 
22     if(len==0) return sg[len][x][y]=sg[len][y][x]=0;
23     if(x>y) swap(x, y);
24     if(len==1 && x==1 && y==2) return sg[len][x][y]=sg[len][y][x]=0;
25     if(len==1) return sg[len][x][y]=sg[len][y][x]=1;
26 
27     bool vs[N];
28     memset(vs, 0, sizeof vs);
29     for(int len1=0; len1<len; len1++) {
30         int len2=len-1-len1;
31         if(len1==0) {
32             if(x==0) {
33                 vs[GET_SG(len2, 1, y)]=1;
34                 vs[GET_SG(len2, 2, y)]=1;
35             }
36             else vs[GET_SG(len2, x, y)]=1;
37         }
38         else if(len2==0) {
39             if(y==0) {
40                 vs[GET_SG(len1, x, 1)]=1;
41                 vs[GET_SG(len1, x, 2)]=1;
42             }
43             else vs[GET_SG(len1, x, y)]=1;
44         }
45         else {
46             vs[GET_SG(len1, x, 1)^GET_SG(len2, 1, y)]=1;
47             vs[GET_SG(len1, x, 2)^GET_SG(len2, 2, y)]=1;
48         }
49     }
50     for(int i=0; i<N; i++) if(!vs[i]) return sg[len][x][y]=sg[len][y][x]=i;
51 }
52 
53 int main() {
54     memset(sg, -1, sizeof sg);
55     for(int i=0; i<=100; i++)
56         for(int j=0; j<3; j++)
57             for(int k=0; k<3; k++) if(sg[i][j][k]==-1) GET_SG(i, j, k);
58     for(int r, n; scanf("%d%d", &r, &n)!=EOF; ) {
59         for(int i=1; i<=n; i++) scanf("%d%d", &A[i].id, &A[i].val);
60         A[0].id=0, A[0].val=0, A[n+1].id=r+1, A[n+1].val=0;
61         n+=2;
62         sort(A, A+n);
63         int sum=0;
64         for(int i=1; i<n; i++) sum^=sg[A[i].id-A[i-1].id-1][A[i-1].val][A[i].val];
65         if(sum) printf("WIN\n");
66         else printf("LOSE\n");
67     }
68     return 0;
69 }
C. More Reclamation

 

題目連接 & AC 通道

 

MemSQL start[c]up Round 2 - online version C. More Reclamation

相關文章
相關標籤/搜索