1. 程式人生 > >bzoj1413 [ZJOI2009]取石子遊戲

bzoj1413 [ZJOI2009]取石子遊戲

測試 bits 個人 include () reg space define net

Description

在研究過Nim遊戲及各種變種之後,Orez又發現了一種全新的取石子遊戲,這個遊戲是這樣的: 有n堆石子,將這n堆石子擺成一排。遊戲由兩個人進行,兩人輪流操作,每次操作者都可以從最左或最右的一堆中取出若幹顆石子,可以將那一堆全部取掉,但不能不取,不能操作的人就輸了。 Orez問:對於任意給出一個初始一個局面,是否存在先手必勝策略。

Input

文件的第一行為一個整數T,表示有 T組測試數據。對於每組測試數據,第一行為一個整數n,表示有n堆石子;第二行為n個整數ai,依次表示每堆石子的數目。

Output

對於每組測試數據僅輸出一個整數0或1。其中1表示有先手必勝策略,0表示沒有。

Sample Input

1
4
3 1 9 4

Sample Output

0

數據範圍
對於30%的數據 n≤5 ai≤105
對於100%的數據 T≤10 n≤1000 每堆的石子數目≤109

正解:博弈論。

推薦一篇題解

這道題實在是太神辣。。

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 
 6 using namespace std;
 7 
 8 int fl[1005][1005
],fr[1005][1005],a[1005],n; 9 10 il int gi(){ 11 RG int x=0,q=1; RG char ch=getchar(); 12 while ((ch<0 || ch>9) && ch!=-) ch=getchar(); 13 if (ch==-) q=-1,ch=getchar(); 14 while (ch>=0 && ch<=9) x=x*10+ch-48,ch=getchar(); 15 return q*x; 16 } 17 18 il void
work(){ 19 n=gi(); 20 for (RG int i=1;i<=n;++i) fl[i][i]=fr[i][i]=a[i]=gi(); 21 for (RG int k=1;k<n;++k){ 22 for (RG int i=1,j,p,q;i<=n-k;++i){ 23 j=i+k,p=fl[i][j-1],q=fr[i][j-1]; 24 if (a[j]==q) fl[i][j]=0; 25 else if ((a[j]<p && a[j]<q) || (a[j]>p && a[j]>q)) fl[i][j]=a[j]; 26 else if (a[j]>=p && a[j]<q) fl[i][j]=a[j]+1; 27 else fl[i][j]=a[j]-1; 28 p=fr[i+1][j],q=fl[i+1][j]; 29 if (a[i]==q) fr[i][j]=0; 30 else if ((a[i]<p && a[i]<q) || (a[i]>p && a[i]>q)) fr[i][j]=a[i]; 31 else if (a[i]>=p && a[i]<q) fr[i][j]=a[i]+1; 32 else fr[i][j]=a[i]-1; 33 } 34 } 35 puts(a[1]==fl[2][n] ? "0" : "1"); return; 36 } 37 38 int main(){ 39 #ifndef ONLINE_JUDGE 40 freopen("game.in","r",stdin); 41 freopen("game.out","w",stdout); 42 #endif 43 RG int T=gi(); 44 while (T--) work(); 45 return 0; 46 }

bzoj1413 [ZJOI2009]取石子遊戲