uva 1378 - A Funny Stone Game sg博弈
阿新 • • 發佈:2017-07-23
1.0 mat cto i+1 clas typedef article 移動 post
題意:David 玩一個石子遊戲。
遊戲中,有n堆石子,被編號為0..n-1。兩名玩家輪流取石子。 每一輪遊戲。每名玩家選取3堆石子i,j,k(i<j,j<=k,且至少有一枚石子在第i堆石子中)。 從i中取出一枚石子,並向j。k中各放入一枚石子(假設j=k則向k中放入2顆石子)。
最 先不能取石子的人輸。 石子堆的個數不會超過23。每一堆石子不超過1000個。
解法:看上去是將石子都往右移,直到全部都到了n-1堆不能移為止。
首先是考慮每堆石子事實上是獨立的一個子遊戲,堆與堆之間不相互影響。
然後就是個數是偶數的對不會影響必勝必敗態,必敗態無法通過移動偶數堆得石子來扭轉局面。由於必勝者僅僅需對稱操作就可以。所以每堆石子就成了01的狀態,sg值僅僅是跟位置有關系了。預處理出每一個位置的sg值就可以。計算第一個可行步驟時候。暴力推斷ijk就可以。
代碼:
/****************************************************** * @author:xiefubao *******************************************************/ #pragma comment(linker, "/STACK:102400000,102400000") #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <vector> #include <algorithm> #include <cmath> #include <map> #include <set> #include <stack> #include <string.h> //freopen ("in.txt" , "r" , stdin); using namespace std; #define eps 1e-8 #define zero(_) (_<=eps) const double pi=acos(-1.0); typedef long long LL; const int Max=100010; const LL INF=0x3FFFFFFF; int sg[100]; bool rem[100]; int n; void init() { sg[0]=0; for(int i=1; i<=25; i++) { memset(rem,0,sizeof rem); for(int j=i-1; j>=0; j--) for(int k=j; k>=0; k--) { rem[sg[j]^sg[k]]=1; } int t=0; while(rem[t]) t++; sg[i]=t; } } bool help[100]; //0 1 2 4 7 8 11 13 14 16 19 21 22 25 26 28 31 32 35 37 38 41 42 int main() { init(); int kk=1; while(cin>>n&&n) { memset(help,0,sizeof help); int ans=0; for(int i=0; i<n; i++) { int a; scanf("%d",&a); if(a)help[i]=1; if(a&1) { ans^=sg[n-1-i]; } } printf("Game %d: ",kk++); if(ans) { for(int i=0; i<n-1; i++) { if(help[i]) { for(int j=i+1; j<n; j++) for(int k=j; k<n; k++) { if((ans^sg[n-1-i]^sg[n-1-j]^sg[n-1-k])==0) { printf("%d %d %d\n",i,j,k); goto end; } } } } end: ; } else puts("-1 -1 -1"); } return 0; }
uva 1378 - A Funny Stone Game sg博弈