BZOJ 1413: [ZJOI2009]取石子游戏

Description

有\(n\)堆石子,将这\(n\)堆石子摆成一排。游戏由两个人进行,两人轮流操作,每次操作者都可以从最左或最右的一堆中取出若干颗石子,可以将那一堆全部取掉,但不能不取,不能操作的人就输了。

Solution

博弈+区间DP.

这道题好厉害啊qwq...

首先一个区间\([l,r]\)在左边或右边添加一个数是个\(P\)一定仅有一个。
因为有另一个的话,从另一个可以转移到当前这个或者从这个可以转移到另一个\((x=y+\Delta)\),所以仅存在一个。
有了这个性质,可以考虑递推。
设\(L[i][j]\)表示在区间\([i,j]\)左边添加\(L[i][j]\)是\(P\)态,\(R[i][j]\)表示在区间\([i,j]\)右边添加\(R[i][j]\)是\(P\)态。
从\([i,j-1]\)来计算\(L[i][j]\),为了表示方便令\(x=L[i][j-1],y=R[i][j-1],z=a[j]\).
1. 若\(y=z\)这个区间是必败的,所以\(L[i][j]=0\)。
2. 若\(x,y<z || z<x,y\),那么\(L[i][j]=z\),因为取走左右一堆的是必败的,所以后手只需要和先手相同即可。
3. 若\(x\leqslant z<y\),那么\(L[i][j]=z+1\),以为如果取到\(x\),后手取到\(x+1\),若取到\(x+1\),后手取到\(x+2\),若小于\(x\),后手只需要保证相等即可。
4. 若\(y<z\leqslant x\),跟上边类似\(L[i][j]=z-1\)。

这道题主要就是在考虑后手的操作。

Code

/**************************************************************
    Problem: 1413
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:204 ms
    Memory:9904 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
 
const int N = 1050;
 
inline int in(int x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
 
int T,n;
int a[N];
int L[N][N],R[N][N];
 
int main() {
    for(T=in();T--;) {
        n=in();
        for(int i=1;i<=n;i++) a[i]=in(),L[i][i]=R[i][i]=a[i];
        for(int i=n;~i;--i) for(int j=i+1;j<=n;j++) {
            int x=L[i][j-1],y=R[i][j-1],z=a[j];
            if(y==z) L[i][j]=0;
            else {
                if(z<x && z<y) L[i][j]=z;
                else if(x<=z && z<y) L[i][j]=z+1;
                else if(y<z && z<=x) L[i][j]=z-1;
                else if(x<z && y<z) L[i][j]=z;
            }
            x=R[i+1][j],y=L[i+1][j],z=a[i];
            if(y==z) R[i][j]=0;
            else {
                if(z<x && z<y) R[i][j]=z;
                else if(x<=z && z<y) R[i][j]=z+1;
                else if(y<z && z<=x) R[i][j]=z-1;
                else if(x<z && y<z) R[i][j]=z;
            }
        }
        printf("%d\n",(n==1||a[1]!=L[2][n]));
    }return 0;
}

  

posted @ 2017-03-14 16:44  北北北北屿  阅读(206)  评论(0编辑  收藏  举报