zoukankan      html  css  js  c++  java
  • 【Luogu】P2599取石子游戏(博弈论)

      题目链接

      情况非常复杂,事实上题解我现在也没有完全理解

      不过大致的意思就是

      设两个数组lef[][],rig[][]表示对应区间左端加一堆数量为lef[][]的石子使得先手必败,rig同理

      可以通过一堆证明证明求出来的值具有唯一性

      所以最后需要判断lef[2][n]是不是等于a[1]。

      对于一段区间[i,j]我们设L=lef[i][j-1],R=rig[i][j-1],X=a[j]

      据说lef[i][j]只跟这三个数有关

      情况大致分以下五种

      1:R=X,此时lef[i][j]=0,因为此时[i,j]已经必败了,左边瞎搞就好

      2:X<L&&X<R,此时lef[i][j]=X,因为这样左右两边就能对齐,然后后手占据主动,然后递归。

      3:X<L&&X>R,此时lef[i][j]=X-1,因为这时候先手在左边拿,后手从右边xjb拿成同样结果就行;如果先手在右边拿,后手从左边拿完全可以绕回当前的局势来,如果先手把右边拿到R,后手直接把lef[][]加的那堆石子清空,先手就GG了

      4:X>=L&&X<R,跟4完全相反

      5:X>L&&X>R,lef[i][j]=x。

      rig[][]求法跟lef[][]对称。

      

    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<cctype>
    #define maxn 2020
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int lef[maxn][maxn];
    int rig[maxn][maxn];
    
    int main(){
        int T=read();
        while(T--){
            int n=read();
            for(int i=1;i<=n;++i)    lef[i][i]=rig[i][i]=read();
            for(int len=2;len<n;++len)
                for(int i=1;i+len-1<=n;++i){
                    int j=i+len-1;
                    int L=lef[i][j-1],R=rig[i][j-1],x=lef[j][j];
                    if(R==x)            lef[i][j]=0;
                    else if(x<L&&x<R)    lef[i][j]=x;
                    else if(x<L&&x>R)    lef[i][j]=x-1;
                    else if(x<R&&x>=L)    lef[i][j]=x+1;
                    else if(x>L&&x>R)    lef[i][j]=x;
                    
                    L=rig[i+1][j],R=rig[i+1][j],x=lef[i][i];
                    if(L==x)            rig[i][j]=0;
                    else if(x<L&&x<R)    rig[i][j]=x;
                    else if(x>L&&x<R)    rig[i][j]=x-1;
                    else if(x<L&&x>=R)    rig[i][j]=x+1;
                    else if(x>L&&x>R)    rig[i][j]=x;
                }
            if(lef[2][n]==lef[1][1])    printf("0
    ");
            else                        printf("1
    ");
        }
        return 0;
    }
  • 相关阅读:
    隐藏 MOSS 2007 页面版本工具栏
    用于显示原始XML形式的搜索结果的XSLT
    MOSS 2007 日志设置
    在布局页面“文章页面中”添加,自定义UserControl
    MOSS 2007 最简单的自定义搜索框 SearchBox
    Asp.net常用状态管理方案分析
    提高asp.net的性能的几种方法(转)
    VS2005下如何用预编译命令来发布站点
    asp.net控件设计时支持(1)
    解决Enterprise Library January 2006不能加密配置文件的方法(转)
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8678702.html
Copyright © 2011-2022 走看看