原题:(CIA面试题?) (参考链接: http://club.pchome.net/topic_1_15_3420979_1__.html)

两个人A和B玩游戏。方法是:A选定一个长度为3的正反序列“正反反”,B选定另一个不同的长度为3的正反序列正正反
现在开始反复丢一枚出现正反的可能性都是1/2的硬币,直到出现A或B选定的正反序列为止。谁的序列出现了,谁就是赢家。问A和B获胜的概率各是多少?

一开始闷住了,那些已经淡忘的排队论啊马尔可夫链啊在乱转,感觉很害怕,希望不要和那些东西沾上边。

定一下神发现不关马尔可夫什么事情(当然,不是真的无关)。是CS一路的,二叉树。

<正>  (0,1)  (A没戏了)

<正>

反    B  (0,1)

(正)

(正)

[反]

反    A  (1,0)

初始点

<正>

(正)

[反]

[反]

(正)

[反]

[反]

这棵树里,对相同括号的节点,从其开始的子树的A,B获胜概率组合是一致的,于是对圆括号(设A获胜概率为P1)和方括号(设A获胜概率为P2)列式:

P1 = 0.5×P2

P2 = 0.5×P1 + 0.5

于是P1 = 1/3

所以在初始点0.5×P1+0.5×P2=0.5。即总的来说A,B的获胜概率相等,和直觉一样(当然直觉还是有些摇摆的)。

题目出的比较次,如果B选其他的(比如反正反?)就有些分别了。不知道在考什么,考直觉?不像(当然如果考生都是像后天中的sam那样口算微积分的则另当别论)。

经dede提醒发现可能算错,重算一次:划线节点的概率和初始点相同。列式结果:A(正反反)获胜概率1/3,B(正正反)获胜概率2/3。这个问题容易算错的地方就是在节点归类上。(再次验证以下程序在节点归类上是正确的)

感谢dede (Robbie T. Mosaic)提供的基于(伪)随机数的C#仿真程序。一开始这个程序有点问题,dede也抱怨“反正反”情形似乎也是各0.5概率。后来终于发现是数组初始化值为0改变了初始条件。以下是演示“反正反”和“正正反”的代码。改了代码运行后,我发现输出结果和理论计算不一致(“正正反”获胜的概率大),经过验算才发现是我算错了,然后把结果和dede谈了一下。直觉来看“正正反”的概率大,因为一旦进入“正正”模式就是“正正反”的天下了。

using System; public class TestProg { public readonly int LastCount = 3; public static void Main() { TestProg prog = new TestProg(); prog.NsMain(); } public void NsMain() { Random rand = new Random(); int i; int count; for (i = 0, count = 0; i < 1000; i++) { count += DoOneRound(rand); } Console.WriteLine("PNP won {0} times out of {1}", count, 1000); } public int DoOneRound(Random rand) { int[] lastthree = new int[LastCount]; int j; for (j = 0; j < LastCount; j++) { lastthree[j] = -1; } while(true) { for (j = 0; j < LastCount - 1; j++) { lastthree[j] = lastthree[j + 1]; } lastthree[j] = rand.Next() % 2; if (lastthree[0] == 0 && lastthree[1] == 1 && lastthree[2] == 0) { Console.WriteLine("NPN wins"); return 0; } else if (lastthree[0] == 1 && lastthree[1] == 1 && lastthree[2] == 0) { Console.WriteLine("PPN wins"); return 1; } } } }

看来这个问题还是比较容易算错的,我想把算法整理一下变成代码:

using System; using System.Collections.Generic; namespace CoinGames { class Whowins { class WinningCondition { public int[][] Sequences = null; public int[][] Rescuers = null; bool IsEqual(int[] seq, int aStart, int aEnd, int bStart, int bEnd) { int ap; int bp; for (ap = aStart, bp = bStart; ap < aEnd && bp < bEnd; ap++, bp++) { if (seq[ap] != seq[bp]) { return false; } } if (ap < aEnd || bp < bEnd) { return false; } return true; } // it gave me a reminiscence of KMP // but it's stronger int[] Rescue(int[] seq) { int n = seq.Length; int[] resq = new int[n]; foreach (int s in seq) { Console.Write(s); } Console.WriteLine(); for (int i = 0; i < n; i++) { resq[i] = -1; for (int j = i - 1; j >= 0; j--) { if (IsEqual(seq, 0, j, i - j, i) && seq[i] != seq[j]) { resq[i] = j; break; } } } foreach (int s in resq) { Console.Write(s); } Console.WriteLine(); return resq; } public void Rescue() { Rescuers = new int[Sequences.Length][]; for (int i = 0; i < Sequences.Length; i++) { Rescuers[i] = Rescue(Sequences[i]); } } public State Transition(State state, int c) { State newState = new State(state); for (int i = 0; i < this.Sequences.Length; i++) { if (this.Sequences[i][newState.Pos[i]] == c) { // An ordinary progress newState.Pos[i]++; } else { do { newState.Pos[i] = Rescuers[i][newState.Pos[i]]; } while (newState.Pos[i] >= 0 && Sequences[i][newState.Pos[i]] != c); newState.Pos[i]++; } if (newState.Pos[i] == Sequences[i].Length) { newState.bHasWinner = true; } } return newState; } } class State : IComparable<State> { // deja vu? yes, inspired by LR syntactical parsing! public int[] Pos = null; public bool bHasWinner = false; public override String ToString() { String r = "["; bool first = true; foreach (int p in Pos) { if (first) { first = false; } else { r += ","; } r += p.ToString(); } r += "]"; return r; } public State(WinningCondition wc) { Pos = new int[wc.Sequences.Length]; for (int i = 0; i < this.Pos.Length; i++) { Pos[i] = 0; } } public State(State that) { Pos = new int[that.Pos.Length]; for (int i = 0; i < that.Pos.Length; i++) { Pos[i] = that.Pos[i]; } } public int CompareTo(State that) { for (int i = 0; i < Pos.Length; i++) { int thisPos = this.Pos[i]; int thatPos = that.Pos[i]; int cmp = thisPos.CompareTo(thatPos); if (cmp != 0) { return cmp; } } return 0; } } static void Main(String[] args) { try { double[] probList = new double[]{0.5, 0.5}; WinningCondition wc = new WinningCondition(); wc.Sequences = new int[][]{new int[]{0,1,0}, new int[]{1,1,0}}; wc.Rescue(); State root = new State(wc); Queue<State> q = new Queue<State>(); List<State> states = new List<State>(){root}; q.Enqueue(root); while (q.Count > 0) { State state = q.Dequeue(); // print out the formula for the node String formula = state + " = "; for (int i = 0; i < probList.Length; i++) { State newState = wc.Transition(state, i); int index = states.BinarySearch(newState); if (index < 0 && !newState.bHasWinner) { index = -index - 1; states.Insert(index, newState); q.Enqueue(newState); } if (i != 0) { formula += " + "; } formula += "(P{" + i + "}=" + probList[i] + ")"; formula += " * "; formula += newState; } Console.WriteLine(formula); } } catch (Exception e) { Console.WriteLine("Exception/n {0}", e); } } } }

经过一番调试,应该输出正确了。结果是NPN胜率3/8。这个程序给出的是围绕某个玩家的各节点的求解算式,如果要排成线性方程组,还需要若干代码,然后可以交给Matlab求解;如果要一般性解出方程,还需加高斯消去法之类(这个问题中矩阵是稀疏的应该有快速算法);为了解出解析解,需要实现有理数类并完成运算方法或重载。至此初步完成这个问题的全部机器求解。总的来看C#的代码紧凑性还是很高的,一般我求解问题代码不太精简,但在这里200行代码也就解决问题的核心部分,而且代码的可读性也不错。

转载于:https://www.cnblogs.com/quanben/archive/2009/03/02/3128947.html

见鬼,结果还就这样了相关推荐

  1. 《网站分析师实战指南》一2.6 让例行公事的报告见鬼去吧

    本节书摘来自异步社区<网站分析师实战指南>一书中的第2章,第2.6节,作者[美]Brent Dykes,更多章节内容可以访问云栖社区"异步社区"公众号查看 2.6 让例 ...

  2. mysql 删除数据 降低_活见鬼,明明删除了数据,空间却没减少!

    原标题:活见鬼,明明删除了数据,空间却没减少! 作者 |莱乌 来源 |IT界农民工 迁移数据常用 1.导出文件 -mysqldump 命令 ‍mysqldump‍是 Mysql 自带的逻辑备份工具.其 ...

  3. 什么TDD,让它见鬼去吧!

    小王是个积极进取的程序员, 在日常工作之余,他还学习单元测试,重构等编程实践. 突然有一天晚上他看到微信群里在激烈地争论一个叫TDD的东西,不由地来了兴致,上网搜索了一下. 原来TDD就是Test D ...

  4. (转)见鬼十法和防见鬼十招

    见鬼十法 1.换眼角膜:换上死人的眼角膜,睁开眼,他们就在身边. 2.孕妇跳楼:跳楼的瞬间,你会看到你不想看的. 3.杯仙:一个杯子.一张纸,大家将手指按住杯底,鬼魂便因号召而来.但请鬼容易送鬼难. ...

  5. 民间秘术——见鬼三招

    相信世上有鬼的人,说起鬼来煞有介事.但对那些不信有鬼的人,谈起鬼来就一笑置之了! 你呢?你信不信有鬼呢?不过在此我们愿意介绍你三种「活见鬼」的招术,要是见「鬼」了,可不要怪我们喔! ●第一招:躲在道士 ...

  6. 特斯拉大半夜「见鬼」!空无一人的路上,它却看见「幽灵」秒刹车

    金磊 贾浩楠 发自 凹非寺 量子位 报道 | 公众号 QbitAI 讲个「鬼故事」: 夜深人静,一辆特斯拉Model X在空无一人的公路上行驶着. 瞬间!它看到了「人类看不见的东西」,于是便刹车在路上 ...

  7. 计算机短暂黑屏,真是见鬼!电脑一玩英雄联盟就会短暂黑屏,这到底是怎么回事?...

    电脑由硬件与软件两个部分组成,硬件指看得见抓得着的实物,比如处理器.硬盘.内存条等硬件,而软件则是指我们常说的操作系统,如Windows系统.OS系统.Linux系统,二者相辅相成,任何一部分出现了问 ...

  8. 活见鬼,明明删除了数据,空间却没减少!

    迁移数据常用 1.导出文件 - mysqldump 命令 ‍mysqldump ‍是 Mysql 自带的逻辑备份工具.其备份原理是通过协议连接到 Mysql 数据库,将需要备份的数据查询出来转换成对应 ...

  9. 停止坐井观天,是时候让“我个人认为”见鬼去了!

    不知道从什么时候开始,在互联网BBS上.在和同学交流一些涉及到强烈个人立场或看法时,我都习惯性的在每句话的前面或后面加上一句:"我个人认为...".今天反思一下这个习惯是怎么养成的 ...

最新文章

  1. 口的内存映射 stm32f7_STM32F7高速缓存
  2. [BZOJ3214][ZJOI2013]丽洁体(Hash+DP)
  3. PHP动态网页转换HTML的一个简单办法
  4. spring batch @EnableBatchProcessing作用
  5. 搭建基础架构-Page
  6. 【网络收集】order by 自定义排序
  7. java map 实例_java中map集合嵌套形式简单示例
  8. postgresql-9.6.6主从
  9. 博弈指什么棋_格局:什么是格局?(胜读十年书)
  10. 怎么使用PVS stream Linux
  11. restfulframework详解
  12. DSP 基于 TMS320F2803x 的 I2C 上的 PMBus 的软件应用
  13. Matlab语言标点说明
  14. 推荐一个下载简历模板的网站工具
  15. 2022年兽药行业发展前景
  16. 小白刷LeeCode(算法篇)7
  17. 毕业寄语 | 关于毕业季的温柔文案
  18. 快速拔h型钢拔桩机 H型钢建筑拔桩机应用特点
  19. ios微信多开教程(最简单实用 亲测可用)
  20. 学习3D建模多久才能工作呢

热门文章

  1. 计算机再带word打不开,word打不开,详细教您怎么解决word打不开
  2. python del函数_干货:Python的内存管理办法
  3. Java实现均摊_Java均摊复杂度和防止复杂度的震荡原理分析
  4. rocketmq 消息指定_RocketMq 实际案例–普通消息的发送
  5. 俩台电脑怎么设置同一局域网_【必看】局域网ip地址不够用怎么办?
  6. 5.QML动画——分组动画
  7. 1.QML语法、属性和元素
  8. ESX虚拟机文件列表详解
  9. 《使用CSLA 2019:CSLA .NET概述》原版和机译文档下载
  10. 使用 Caddy 自动化发布 Web 应用