2018.07.15【省赛模拟】模拟B组 【GDOI2016模拟3.11】游戏

#Description
这里写图片描述

#Input
这里写图片描述

#Output
这里写图片描述

#Sample Input
2 2
RL
LR
2 2
RR
RR

#Sample Output
LOSE
WIN

#Data Constraint
这里写图片描述

#题解
10%对于n=1,直接特判即可。
30%对于n,m<=3,可以用暴搜的方法跑过去。
60%对于另外的30%,打表“WIN”,别问我为什么。加上刚才的30分,即有60分。
好了,上面的东西太简单了,太肤浅了,我们来看看100分这么做。
首先,这是一道博弈论题废话
我们首先看看题意,发现:
L表示左上到右下一条都改成不活动的点(碰到不活动的点或边界截止)
R表示左下到右上一条都改成不活动的点(碰到不活动的点或边界截止)
X上面两个方向都改成不活动的点(碰到不活动的点或边界截止)
好的,就是这3种操作。
那么我们看看图:
这里写图片描述
我们发现,黑色格子上的操作不会影响白色格子,反之亦然。
那么我们就可以把原图分成两个棋局——
这里写图片描述
(注意:这两个图是拉直后的图而且灰色表示不存在的点)
这两个图中,三个操作也变了——
L表示上到下一条都改成不活动的点(碰到不活动的点或边界截止)
R表示左到右一条都改成不活动的点(碰到不活动的点或边界截止)
X上面两个方向都改成不活动的点(碰到不活动的点或边界截止)

然后呢,我们看看——由于每次选择一个操作,那么就会把当前的棋局分成2或4个独立的局面(看图)
这里写图片描述
然后,我们就可以用小的局面,推导到大的局面。
那么我们就可以设sg函数:
sg[sx,sy,ex,ey]表示以(sx,sy)和(ex,ey)为两个顶点的矩形中的mex值。
你问我sg函数是什么?
sg的定义:mex{sg[son1],sg[son2],……,sg[sonn]}
你问我sg定理是什么?
sg的定理:当,sg1sg2sg3……sgm>0时,先手胜,否则先手败。
证明?可以在“取石子游戏”这道题中,利用二进制来感性理解。
真正精确的证明我不会。

于是乎,我们就在一个大的局面中,枚举选择某个点之后,求出分成的2或4个小局面的sg值,把他们xor起来,然后,就可以把这个点的结果丢到大局面的sg的mex中,最后求一求mex,就可以得到大局面的sg值。
那么,我们可以利用递归的思想来做。
注意初始化和边界条件。
还有就是坑爹的栈和构图(构建新的图,要推好久)

标程:

var
        i,j,k,l,n,m,maxm,maxn,p,q,maxx,maxy,now:longint;
        map:array[1..20,1..20] of char;
        op:array[1..20,1..20] of char;
        sg:array[1..20,1..20,1..20,1..20] of longint;
        first,second:longint;
function max(x,y:longint):longint;
begin
        if x>y then exit(x);
        exit(y);
end;
function dg(sx,sy,ex,ey:longint):longint;
var
        i,j,k,l:longint;
        jl:array[0..4] of longint;
        p:array[0..400] of longint;
begin
        p[0]:=0;
        for i:=sx to ex do
        begin
                for j:=sy to ey do
                begin
                        if op[i,j]<>' ' then
                        begin
                                if op[i,j]='L' then
                                begin
                                        jl[0]:=2;
                                        if j>sy then
                                        begin
                                                if sg[sx,sy,ex,j-1]<>-1 then
                                                jl[1]:=sg[sx,sy,ex,j-1]
                                                else
                                                jl[1]:=dg(sx,sy,ex,j-1);
                                        end
                                        else
                                        jl[1]:=0;
                                        if j<ey then
                                        begin
                                                if sg[sx,j+1,ex,ey]<>-1 then
                                                jl[2]:=sg[sx,j+1,ex,ey]
                                                else
                                                jl[2]:=dg(sx,j+1,ex,ey);
                                        end
                                        else
                                        jl[2]:=0;
                                end
                                else
                                if op[i,j]='R' then
                                begin
                                        jl[0]:=2;
                                        if i>sx then
                                        begin
                                                if sg[sx,sy,i-1,ey]<>-1 then
                                                jl[1]:=sg[sx,sy,i-1,ey]
                                                else
                                                jl[1]:=dg(sx,sy,i-1,ey);
                                        end
                                        else
                                        jl[1]:=0;
                                        if i<ex then
                                        begin
                                                if sg[i+1,sy,ex,ey]<>-1 then
                                                jl[2]:=sg[i+1,sy,ex,ey]
                                                else
                                                jl[2]:=dg(i+1,sy,ex,ey);
                                        end
                                        else
                                        jl[2]:=0;
                                end
                                else
                                if op[i,j]='X' then
                                begin
                                        jl[0]:=4;
                                        if (i>sx) and (j>sy) then
                                        begin
                                                if sg[sx,sy,i-1,j-1]<>-1 then
                                                jl[1]:=sg[sx,sy,i-1,j-1]
                                                else
                                                jl[1]:=dg(sx,sy,i-1,j-1);
                                        end
                                        else
                                        jl[1]:=0;
                                        if (i>sx) and (j<ey) then
                                        begin
                                                if sg[sx,j+1,i-1,ey]<>-1 then
                                                jl[2]:=sg[sx,j+1,i-1,ey]
                                                else
                                                jl[2]:=dg(sx,j+1,i-1,ey);
                                        end
                                        else
                                        jl[2]:=0;
                                        if (j>sy) and (i<ex) then
                                        begin
                                                if sg[i+1,sy,ex,j-1]<>-1 then
                                                jl[3]:=sg[i+1,sy,ex,j-1]
                                                else
                                                jl[3]:=dg(i+1,sy,ex,j-1);
                                        end
                                        else
                                        jl[3]:=0;
                                        if (j<ey) and (i<ex) then
                                        begin
                                                if sg[i+1,j+1,ex,ey]<>-1 then
                                                jl[4]:=sg[i+1,j+1,ex,ey]
                                                else
                                                jl[4]:=dg(i+1,j+1,ex,ey);
                                        end
                                        else
                                        jl[4]:=0;
                                end;
                                inc(p[0]);
                                p[p[0]]:=jl[1];
                                for k:=2 to jl[0] do
                                begin
                                        p[p[0]]:=jl[k] xor p[p[0]];
                                end;
                                p[p[0]]:=p[p[0]];
                        end;
                end;
        end;
        for i:=1 to p[0] do
        begin
                for j:=i+1 to p[0] do
                begin
                        if p[i]>p[j] then
                        begin
                                k:=p[i];
                                p[i]:=p[j];
                                p[j]:=k;
                        end;
                end;
        end;
        j:=-1;
        for i:=1 to p[0] do
        begin
                if p[i]=j+1 then
                begin
                        j:=j+1;
                end
                else
                if p[i]>j+1 then
                begin
                        sg[sx,sy,ex,ey]:=j+1;
                        exit(j+1);
                end;
        end;
        if p[0]=0 then
        begin
                sg[sx,sy,ex,ey]:=0;
                exit(0);
        end
        else
        begin
                sg[sx,sy,ex,ey]:=p[p[0]]+1;
                exit(p[p[0]]+1);
        end;
end;
begin
        while not eof do
        begin
                inc(now);
                readln(n,m);
                for i:=1 to n do
                begin
                        for j:=1 to m do
                        begin
                                read(map[i,j]);
                        end;
                        readln;
                end;
                if (n=1) and (m=1) then
                begin
                        writeln('WIN');
                        continue;
                end;
                for i:=1 to 20 do for j:=1 to 20 do op[i,j]:=' ';
                maxn:=(n-1) div 2;
                maxm:=(m-1) div 2;
                p:=0;
                maxy:=0;
                for i:=1 to maxm+1 do
                begin
                        p:=i;
                        q:=maxn+i;
                        j:=1;
                        k:=1+(i-1)*2;
                        while (j<=n) and (k<=m) do
                        begin
                                op[p,q]:=map[j,k];
                                maxy:=max(maxy,p);
                                inc(p);
                                inc(j);
                                inc(k);
                        end;
                end;
                maxx:=maxm+maxn+1;
                p:=1;
                for i:=1 to maxn do
                begin
                        p:=i+1;
                        q:=maxn-i+1;
                        j:=i*2+1;
                        k:=1;
                        while (j<=n) and (k<=m) do
                        begin
                                op[p,q]:=map[j,k];
                                maxy:=max(maxy,p);
                                inc(p);
                                inc(j);
                                inc(k);
                        end;
                end;
                fillchar(sg,sizeof(sg),255);
                for i:=1 to maxy do
                begin
                        for j:=1 to maxx do
                        begin
                                if op[i,j]=' ' then
                                begin
                                        sg[i,j,i,j]:=0;
                                end
                                else
                                begin
                                        sg[i,j,i,j]:=1;
                                end;
                        end;
                end;
                if now=7 then
                begin
                        now:=now;
                end;
                first:=dg(1,1,maxy,maxx);
                for i:=1 to 20 do for j:=1 to 20 do op[i,j]:=' ';
                maxn:=n div 2;
                maxm:=m div 2;
                p:=0;
                maxy:=0;
                for i:=1 to maxm do
                begin
                        p:=i;
                        q:=maxn+i;
                        j:=1;
                        k:=i*2;
                        while (j<=n) and (k<=m) do
                        begin
                                op[p,q]:=map[j,k];
                                maxy:=max(maxy,p);
                                inc(p);
                                inc(j);
                                inc(k);
                        end;
                end;
                maxx:=maxm+maxn;
                p:=0;
                for i:=1 to maxn do
                begin
                        p:=i;
                        q:=maxn-i+1;
                        j:=i*2;
                        k:=1;
                        while (j<=n) and (k<=m) do
                        begin
                                op[p,q]:=map[j,k];
                                maxy:=max(maxy,p);
                                inc(p);
                                inc(j);
                                inc(k);
                        end;
                end;
                fillchar(sg,sizeof(sg),255);
                for i:=1 to maxy do
                begin
                        for j:=1 to maxx do
                        begin
                                if op[i,j]=' ' then
                                begin
                                        sg[i,j,i,j]:=0;
                                end
                                else
                                begin
                                        sg[i,j,i,j]:=1;
                                end;
                        end;
                end;
                second:=dg(1,1,maxy,maxx);
                if first xor second=0 then writeln('LOSE')
                else writeln('WIN');
        end;
end.
我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
原文地址:https://www.cnblogs.com/RainbowCrown/p/11148403.html