1. 程式人生 > >【GDOI2016模擬3.11】遊戲

【GDOI2016模擬3.11】遊戲

Description

這裡寫圖片描述

Input

這裡寫圖片描述

Output

這裡寫圖片描述

Sample Input

2 2
RL
LR
2 2
RR
RR

Sample Output

LOSE
WIN

Data Constraint

這裡寫圖片描述

題解

這道題調了我好久(不要問我為什麼水題要想這麼久)。
看到題目是遊戲,第一想法肯定是SG函式(過來人的經驗之談)。
然而,由於講題人劉某的表述,使我在錯誤的革命道路上一錯再錯。
後來,我發現:
對於這道題,我們把一個棋盤,拆分成兩個互相獨立的棋盤,因為只有斜著的變化,所以兩個棋盤是互相獨立的(相當於國際象棋裡的黑格和白格)。
接著,我們把棋盤斜過來,每一個操作:
‘R’即橫著切成兩半,‘L’即豎著切成兩半,‘X’即橫豎著切成四塊。每切成塊又互相獨立(因為碰到非活動格即停止拓展)。
那麼,我們可以遞迴搜尋+記憶化剪枝。
對於每一個區間,我們列舉每一個點,將其分割開來,sg值異或一下,再對於所有的sg值,取個mex

1就好了。
code:

uses math;
var
        n,m,i,j,x,y,mx1,my1,sg,mx2,my2:longint;
        a:array[0..20,0..20]of char;
        x1,x2:array[0..500,0..500,1..2]of longint;
        g:array[0..20,0..20,0..20,0..20,1..2]of longint;
function dg(stx,sty,enx,eny,tt:longint):longint;
var
        i,j,sgg,x,y,o:longint;
        t:array
[0..200]of longint; begin fillchar(t,sizeof(t),0); if (stx>enx)or(sty>eny) then exit(0); if g[stx,sty,enx,eny,tt]<>-1 then exit(g[stx,sty,enx,eny,tt]); o:=0; for i:=stx to enx do for j:=sty to eny do begin
if tt=1 then begin x:=x1[i,j,1]; y:=x1[i,j,2]; end else begin x:=x2[i,j,1]; y:=x2[i,j,2]; end; if (x<>0)and(y<>0) then inc(o); end; if o=1 then begin g[stx,sty,enx,eny,tt]:=1; exit(1); end; sgg:=0; for i:=stx to enx do begin for j:=sty to eny do begin if tt=1 then begin x:=x1[i,j,1]; y:=x1[i,j,2]; end else begin x:=x2[i,j,1]; y:=x2[i,j,2]; end; if (x=0)or(y=0) then continue; inc(o); case a[x,y] of 'R':sgg:=dg(stx,sty,i-1,eny,tt) xor dg(i+1,sty,enx,eny,tt); 'L':sgg:=dg(stx,sty,enx,j-1,tt) xor dg(stx,j+1,enx,eny,tt); 'X':sgg:=dg(stx,sty,i-1,j-1,tt) xor dg(stx,j+1,i-1,eny,tt) xor dg(i+1,sty,enx,j-1,tt) xor dg(i+1,j+1,enx,eny,tt); end; t[sgg]:=1; end; end; if o=1 then begin g[stx,sty,enx,eny,tt]:=1; exit(1); end; for i:=0 to 200 do if t[i]=0 then begin g[stx,sty,enx,eny,tt]:=i; exit(i); end; end; begin while not eof do begin readln(n,m); fillchar(x1,sizeof(x1),0); fillchar(x2,sizeof(x2),0); fillchar(g,sizeof(g),255); my1:=0; my2:=0; x:=1; y:=n div 2; if n mod 2=1 then inc(y); x1[x,y,1]:=1; x1[x,y,2]:=1; mx1:=1; my1:=1; for i:=1 to n do begin for j:=1 to m do begin read(a[i,j]); if (j+i) mod 2=0 then begin if (i=1)and(j=1) then continue; x:=(i+j) div 2; y:=(n-i+j+1) div 2; mx1:=max(mx1,x); my1:=max(my1,y); x1[x,y,1]:=i; x1[x,y,2]:=j; end else begin x:=(i+j) div 2; y:=(n-i+j+1) div 2; mx2:=max(mx2,x); my2:=max(my2,y); x2[x,y,1]:=i; x2[x,y,2]:=j; end; end; readln; end; sg:=dg(1,1,mx1,my1,1) xor dg(1,1,mx2,my2,2); if sg=0 then writeln('LOSE') else writeln('WIN'); end; end.
  1. mex(u)表示集合內沒有出現過的最小自然數。