ACM博客_kuangbin

博弈-翻硬币游戏

hihoCoder

1172 : 博弈游戏·Nim游戏·二

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

Alice和Bob这一次准备玩一个关于硬币的游戏:
N枚硬币排成一列,有的正面朝上,有的背面朝上,从左到右依次编号为1..N。现在两人轮流翻硬币,每次只能将一枚正面朝上的硬币翻过来,并且可以随自己的意愿,在一枚硬币翻转后决定要不要将该硬币左边的任意一枚硬币也翻一次(正面翻到背面或背面翻到正面)。翻最后一枚正面向上的硬币的人获胜。同样的,这次游戏里面Alice仍然先手,两人均采取最优的策略,对于给定的初始局面,Alice会获胜还是Bob会获胜?

提示:Turning Turtles

输入

第1行:1个正整数N,表示硬币数量。1≤N≤10,000
第2行:1个字符串,第i个字符表示编号为i的硬币状态,’H’表示正面朝上,’T’表示背面朝上。

输出

第1行:1个字符串,若Alice能够获胜输出"Alice",否则输出"Bob"

样例输入

8
HHTHTTHT

样例输出

Bob

Turning Turtles

这个游戏叫做Turning Turtles,它的本质就是Nim游戏。那么它到底是如何转化为Nim游戏的呢?让我们一步一步来分析。

首先,我们先将局面分解一下,每一次我们只考虑一枚硬币。
不妨设所有硬币全部背面朝上的局面为局面0
假设现在N枚硬币,只有第1枚是正面朝上的。该局面只能转化为全部硬币背面朝上的局面。我们假定该局面为 局面1,则局面1可以转化为局面0。
假设只有第2枚是正面朝上的。该局面可以转化为:只有硬币1正面朝上;全部硬币背面朝上。我们假定该局面为 局面2,局面2可以转化为局面1和局面0。
同理我们可以推定,第i枚硬币正面朝上的局面为局面i,局面i可以转化为局面0..i-1。

现在,我们考虑把给定的局面拆成单个硬币的局面集合

比如给定了{HHTHTTHT},其中H表示正面朝上,T表示背面朝上。那么就是当前局面={局面1,局面2,局面4,局面7}。每一次我们可以改变其中个一个局面,当出现局面0时就从集合中删去。
这样一看是不是就变成了Nim游戏了?然而事实并没有那么简单。

进一步分析,若同时存在i,j(j<i)两枚硬币正面朝上。我们将这个局面拆成2个单一的局面:即局面i和局面j。
在反转i的时候我们考虑从局面i转移到局面j,那么我们会有两个局面j。
表示第j枚被反转了2次,也就是回到了背面朝上的状态。
那么我们得到这个游戏一个性质:当出现两个同样的局面时,等价于这两个局面合并变成了局面0。

这种情况在Nim游戏中是没有的,那么它会对Nim游戏的状态造成影响么?
我们想一想,在Nim游戏中,如果出现两个数量相同的堆时,比如A[i]=A[j]。在计算Nim游戏状态时我们采用的xor操作,xor有交换律和结合律。则我们可以变成:
(A[i] xor A[j]) xor Other
因为A[i] = A[j],所以A[i] xor A[j] = 0。上式实际就是:
0 xor Other
也就是说在原Nim游戏中,若出现了两个数量相同的堆时,实际上这两堆已经不对总局面造成影响了,也就可以认为这两对合并为了一个数量为0的堆。

到此,我们可以发现这个硬币游戏完全满足Nim游戏的规则,其解答也满足Nim游戏的性质,这题也就很简单的转化为了普通的Nim游戏。在实际的博弈游戏中会发现很多都是可以转化为Nim游戏模型。如何正确的建立模型和转化游戏模型也就是解决博弈游戏一个很重要的手段。

比如Nimble游戏:
游戏开始时有许多硬币任意分布在楼梯上,共N阶楼梯从地面由下向上编号为0到N。游戏者在每次操作时可以将任意一枚硬币向下移动,直至地面。游戏者轮流操作,将最后一枚硬币移至地面(即第0阶)的人获胜。在双方都采取最优策略的情况下,对于给定的初始局面,问先手必胜还是先手必败。
每一枚硬币仍然对应了一个石子堆,向下移动就等价于从石子堆里面取出石子。

同样的例子还有很多,有些游戏甚至需要做好几次转换才能移动到Nim游戏模型,在之后我们就会见到。

import java.util.*;
import java.math.*;public class Main{static int MAXN=(int)(500+10);public static void main(String[] args) {Scanner cin=new Scanner(System.in);while(cin.hasNext()) {int n=cin.nextInt();String str=cin.next();int len=str.length();int ret=0;for(int i=0;i<len;i++) {if(str.charAt(i)=='H')ret^=(i+1);}if(ret==0)System.out.println("Bob");elseSystem.out.println("Alice");}cin.close();}
}

HDU3537

题意:

有一排硬币,告诉 你n个正面朝上的硬币的位置,你可以选择任意位置的1~3个硬币翻转一下,但是问你先手是否会输。

打表找规律

#include<stdio.h>
#include<string.h>
//统计x的二进制表示中1的个数
static int countOne(int x) {int ans=0;while(x!=0) {if((x&1)!=0)  ans++;x=x>>1;}return ans;
}
int vis[1007],sg[1007];
int main()
{for(int i=1;i<100;i++){memset(vis,0,sizeof(vis));vis[0]=1;//翻一枚for(int j=0;j<i;j++)vis[sg[j]]=1;//翻两枚for(int j=0;j<i;j++)for(int k=0;k<j;k++)vis[sg[j]^sg[k]]=1;//翻三枚for(int k=0;;k++)if(!vis[k]){sg[i]=k;break;}printf("%d,%d,%d\n",i-1,sg[i],countOne(i-1));}
}

规律:

  1. 若X的二进制表示里1的个数为奇数,则SG[x]=2*x;
  2. 若X的二进制表示里1的个数为偶数,则SG[x]=2*x+1;

最后N个X的SG值异或为0,先手必败;

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<math.h>
#include<set>
using namespace std;
const int  maxn = 1e6+10;
typedef long long LL;
//统计x的二进制表示中1的个数
static int countOne(int x) {int ans=0;while(x!=0) {if((x&1)!=0)  ans++;x=x>>1;}return ans;
}
//计算x的SG值
static int SG(int x) {int one=countOne(x);if(one%2==1)return x<<1;//sg=2*x;return x<<1|1;//sg=2*x+1
}
int main()
{int n;while(scanf("%d",&n)!=EOF){set<int>s;//自动去重for(int i=0;i<n;i++){int x;scanf("%d",&x);s.insert(x);}int ret=0;set<int>::iterator it;for(it=s.begin();it!=s.end();it++){//printf("%d\n",*it);ret^=SG(*it);}if(ret==0)printf("Yes\n");elseprintf("No\n");}return 0;
}

浅谈 翻硬币游戏【Nim博弈】相关推荐

  1. HDU-3537 Mock Turtles型翻硬币游戏

    题意:<=10^8不定个硬币,给你n<=100个正面朝上的硬币以及他们所在的位置,可任选1/2/3个硬币反转(不必连续),但要求翻的这1/2/3个硬币中的最右侧的一个是正面朝上的,问先手者 ...

  2. 从翻硬币游戏看敏捷开发

    摘要: 敏捷开发还能这么玩? 本文分享自华为云社区<从翻硬币游戏看敏捷开发>,作者:敏捷的小智. 为了推广敏捷开发的理念,很多敏捷教练都会带领团队做一些敏捷小游戏,今天咱们就来聊聊&quo ...

  3. 浅谈即时战略游戏在 J2ME 上的实现

     浅谈即时战略游戏在 J2ME 上的实现 <星际>.<魔兽>.<文明>......这些都是PC游戏玩家们耳熟能详的名字,可以说以这些游戏为代表的战略游戏是PC游戏的 ...

  4. 浅谈一下DNF游戏小晶块,这个神秘的道具

    DNF的小晶块可以说是跟随版本时间最长的道具之一了,一代一代版本更新而来,有些材料.道具跟随着游戏的版本更新不断的进行更替,神话一般的炉岩碳也在时间的长河中消失了踪影,而小晶块却在版本的长河中不断流淌 ...

  5. 硬币游戏 (博弈入门)

    题目: A 和 B 在玩一个游戏,给定K个数字a1,a2,a3...ak ; 一开始有x个硬币 : A 和 B 轮流取硬币.每次所取硬币的枚数一定在a1,a2,a3..ak ; 里面,A 先取 , 取 ...

  6. 【牛客 - 373A】翻硬币问题(博弈,结论,分析)

    题干: 链接:https://ac.nowcoder.com/acm/contest/373/A 来源:牛客网 Alice和Bob正在玩一个很经典的游戏. 有 n n个硬币初始时全部正面朝上,每一轮A ...

  7. 浅谈人工智能与游戏思维

          如何找到一种可产生意向性的形式化手段是通往人机有效融合的关键,目前的数学.物理手段还不具备完全承担这个重任的能力,因为这仅是智能--这个复杂性系统问题的两个方面而已.       下文首先 ...

  8. HDOJ 3537 Daizhenyang's Coin (翻硬币游戏)

    转载请注明出处,谢谢 http://blog.csdn.net/ACM_cxlove?viewmode=contents           by---cxlove 每次可以翻动一个.二个或三个硬币. ...

  9. 【BZOJ4600】硬币游戏,博弈

    传送门 思路: 考场爆零系列 因为当时博弈pi都不会,连SG函数是啥都不知道 现在会了一点点博弈,来看一下 很快写出了10分(n<=16)做法-- orz Va爷的题解 感觉Va爷的博客思路讲的 ...

最新文章

  1. oracle client中对 TNSNAMES.ORA的研究
  2. Django中Ajax提交数据的CSRF问题
  3. The Genymotion virtual device could not obtain an IP address
  4. Sublime Text3激活
  5. 图像基本处理算法的简单实现(二)
  6. 【LeetCode-SQL每日一练】—— 1179. 重新格式化部门表
  7. vue如何获取年月日_好程序员web前端教程分享Vue相关面试题
  8. testng依赖_TestNG依赖关系–DependOnMethods,dependsOnGroups
  9. SSD固态硬盘4K对齐一键分区
  10. 由于应用程序配置不正确,应用程序未能启动。重新安装应用程序可能会纠正这个问题
  11. invalid method declaration
  12. Python学习笔记:第十四站 百宝箱
  13. NetLogo学习笔记1 —— 初步认识
  14. 【Codesys】-按钮启动外部.exe应用程序,按钮关闭HMI界面,桌面图标启动HMI界面。
  15. Supervisor(四)
  16. 90 后的他带出7 个“师弟”,爱说话的程序员脱单更快?
  17. 从表征到行动---意向性的自然主义进路(续二)
  18. Spring+SpringMVC+MyBatis+easyUI整合优化篇(五)MockMvc服务端的单元测试
  19. 编程语言基础知识点总结程序
  20. 手动安装Eclipse插件

热门文章

  1. Tween 若干年后我尽然还要学数学 曲线到底是什么鬼啊
  2. 基于Vmware player的Windows 10 IoT core + RaspberryPi2安装部署
  3. VS2005 自动生成属性(转)
  4. java佳沃维洛奇,新品速递:JAVA 双雄耀世登场
  5. mysql错误1300怎么解决_pt-osc 变更时遇到 “MySQL error 1300” 报错问题解决
  6. ant构建项目迁移到gradle_自动化构建、自动化部署发布一览
  7. python区块链开发_10个开源的Python区块链项目
  8. mysql 多久备份一次_教你如何通过一次单击自动备份mysql数据库
  9. 手机用鸿蒙,魅族“很聪明”:宣布加入鸿蒙,让大家以为手机用鸿蒙,其实不是...
  10. centos挂载u盘只读_完美解决linux下U盘文件只读的问题