先看一个问题
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 1010 int 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
时间: 2024-10-16 17:40:45