• 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.
    
    我活在这夜里。无论周围多么黑暗,我都要努力发光!我相信着,终有一天,我会在这深邃的夜里,造就一道最美的彩虹。
  • 相关阅读:
    Python 使用gevent下载图片案例
    Python 使用gevent实现多任务
    Python 生成器
    Python 自己实现可迭代对象
    Python 遍历文件夹清理磁盘案例
    Python 多进程拷贝文件夹案例
    Python 多进程编程
    Python 多线程编程
    Python TCP通信之仿文件下载
    Python UDP 通信
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148403.html
Copyright © 2020-2023  润新知