Ferguson游戏
考虑一个简单的游戏:
有两个盒子,其中一个装有m颗糖、另一个装有n颗糖,将这样的状态记为(m,n)。每次的移动是将其中一个盒子清空,把另一个盒子的一些糖拿到被清空的盒子里使得两个盒子至少各有一颗糖。两个操作者轮流进行操作,不能操作者败。需要判断一个状态是否先手必败。
按照k=m+n从小到大的顺序进行判断即可。
1 #include <cstdio> 2 // Ferguson,打印先手必败状态。 3 const int maxn = 100; 4 int winning[maxn][maxn]; // 1为先手必胜、0为先手必败 5 int main(){ 6 winning[1][1] = false; // (1,1)是游戏的唯一终态,此时先手必败 7 for(int k = 3 ; k < 20 ; k++) // k = n + m 8 for(int n = 1 ; n < k ; n++){ 9 int m = k - n; 10 winning[n][m] = false; 11 for(int i = 1 ; i < n ; i++) // 如果之后的存在一个状态是先手必败的 12 if(!winning[i][n - i]) winning[n][m] = true; 13 for(int i = 1 ; i < m ; i++) 14 if(!winning[i][m - i]) winning[n][m] = true; 15 if(n <= m && !winning[n][m]) 16 printf("%d %d\n",n,m); 17 } 18 return 0; 19 }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步