標籤:
先看一個問題
HDU 3595 GG and MM (Every_SG博弈)
題目有N個遊戲同時進行,每個遊戲有兩堆石子,每次從個數多的堆中取走數量小的數量的整數倍的石子。取最後一次的獲勝。並且N個遊戲同時進行,除非遊戲結束,否則必須操作。
現在問題變成了,每次都必須在每個非空石子堆中選擇。
這個問題的核心在於:
對於我們可以贏的單一遊戲,我們一定要拿到這一場遊戲的勝利!
所以,我們只需要考慮如何讓我們必勝的遊戲儘可能長的玩下去。
但是對手卻不希望他必敗的單一遊戲玩的太久,這就是 Every-SG 遊 戲不同於其他 SG 遊戲的地方:一般的 SG 遊戲只有勝與負之間的博弈, 而 Every-SG 遊戲又添加了長與短之間的博弈,這使得 Every-SG 遊戲更 有嚼頭,更有味道。
最後的定理是顯然的,最大的單一遊戲步數如果是奇數的話那麼肯定是先手取得進行最後一步。否則一定是對手取走最後一個棋子。
#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define N 1010int dp[N][N];int dfs(int p,int q){ if(p>q) swap(p,q); if(p==0) { dp[p][q] = 0; return 0;//必敗 } int k = q/p; int tp = q-p*k,tq = p; int flag = dfs(q-p*k,p); if(k==1) { dp[p][q] = dp[tp][tq]+1; return flag^1; } else { if(flag == 0) { dp[p][q] = dp[tp][tq]+1; } else dp[p][q] = dp[tp][tq]+2; return 1; }}int main() { int n; memset(dp,-1,sizeof(dp)); while(cin>>n) { int mx = -1; for(int i=0;i<n;i++) { int p,q; cin>>p>>q; dfs(p,q); mx = max( mx,dp[min(p,q)][max(p,q)] ); } if( (mx&1) ) printf("MM\n"); else printf("GG\n"); } return 0;}hdu3595
每一個可以移動的棋子都要移動——Every-SG 遊戲