Pots of gold game:看谁拿的钱多
问题描述:
Pots of gold game: Two players A & B. There are pots of gold arranged in a line, each containing some gold coins (the players can see how many coins are there in each gold pot - perfect information). They get alternating turns in which the player can pick a pot from one of the ends of the line. The winner is the player which has a higher number of coins at the end. The objective is to "maximize" the number of coins collected by A, assuming B also plays optimally. A starts the game.
The idea is to find an optimal strategy that makes A win knowing that B is playing optimally as well. How would you do that?简单来说就是很多金币罐排成一行,两个人轮流拿钱。每次只能拿走线端的罐,也就两种选择。A先开始,问你A应该用什么策略使得拿到的钱尽可能多。B也很聪明,每次也是“最优”决策
解答:
非常巧妙,动态规划在这里用上了.
因为每次A只有两种选择,选择头部或者尾部的金币罐。我们不妨假设选择头部,那么此时轮到B选择了,B也有两种选择,选择此时的“头部”或者”尾部”。注意到问题是包括了子问题的优化解的,这个特性比较明显就不多做说明了,可以这么理解,“英明”决策是由一个个小的“英明”决策组成。
所以我们可以采用动态规划的方式来解决
1: function max_coin( int *coin, int start, int end ):
2: if start > end:
3: return 0
4:
5: int a = coin[start] +
max
( max_coin( coin, start+2,end ), max_coin( coin, start+1,end-1 ) )
6: int b = coin[end] +
max
( max_coin( coin, start+1,end-1 ), max_coin( coin, start,end-2 ) )
7:
8: return max(a,b)
大家看看这个代码,仔细研究一下有没有问题。
我们来分析一下,锁定第五句,我们用自然语言来解释一下这一句。A选择了线首钱罐,然后根据B的选择有两种情况,去两种情况下的最优解。最优解,最优。。。
分析到这儿,大家有没有感觉到问题的出现?没有的话我们再来看一下。
A选择最优解!这是什么意思,意思就是说B的选择对A没有影响!因为无论B选择是什么,A的选择是一定的。
这显然是不合理的!
所以正确的代码应该是
1: function max_coin( int *coin, int start, int end ):
2: if start > end:
3: return 0
4:
5: int a = coin[start] + min( max_coin( coin, start+2,end ), max_coin( coin, start+1,end-1 ) )
6: int b = coin[end] + min( max_coin( coin, start+1,end-1 ), max_coin( coin, start,end-2 ) )
7:
8: return max(a,b)
看着这段代码,大家可能感觉怪怪的,因为好像就算换成min也不一定就说明B影响到了A的选择。看起来像那么回事,但是对不对呢?
说实话,我没法严谨去证明。
暂时这么理解吧,B采取了一个策略,那就是处处为难A,每次选择遵循了一个原则,那就是使得接下来A获得的总钱币数目尽可能少。A尽可能少那么B也就自然尽可能多了。
QUORA上有这么一段代码,也可以看看,不错的
http://www.quora.com/Dynamic-Programming/How-do-you-solve-the-pots-of-gold-game
pots = [...] cache = {}
def optimal(left, right, player):
if left > right:
return 0
if (left, right, player) in cache:
return cache[(left, right, player)]
if player == 'A':
result = max(optimal(left + 1, right, 'B') + pots[left],
optimal(left, right - 1, 'B') + pots[right])
else:
result = min(optimal(left + 1, right, 'A'),
optimal(left, right - 1, 'A'))
cache[(left, right, player)] = result
return result answer = optimal(0, len(pots)-1, 'A')
Pots of gold game:看谁拿的钱多的更多相关文章
- POJ_2392_Space_Elevator_(动态规划,背包)
描述 http://poj.org/problem?id=2392 磊方块,每种方块有数量,高度,以及该种方块所能处在的最高高度.问最高磊多高? Space Elevator Time Limit: ...
- 使用Unity创建塔防游戏(Part1)
How to Create a Tower Defense Game in Unity - Part1 原文作者:Barbara Reichart 文章原译:http://www.cnblogs.co ...
- 使用unity创建塔防游戏(原译)(part1)
塔防游戏非常地受欢迎,木有什么能比看着自己的防御毁灭邪恶的入侵者更爽的事了. 在这个包含两部分的教程中,你将使用Unity创建一个塔防游戏. 你将会学到如何: 创建一波一波的敌人 使敌人随着路标移动 ...
- [设计模式] javascript 之 代理模式
代理模式说明 说明:顾名思义就是用一个类来代替另一个类来执行方法功能,这个模式跟装饰模式有点相似,不一样的是,代理模式是代替客户初始化被代理对象类,而装饰模式采用接口或初装饰者参数引用的方式来执行的. ...
- python(4) - 装饰器
由于函数也是一个对象,既然是对象就可以将它赋给变量,通过变量来调用该函数 def now(): print('2016-01-01') f = now #注意,这里不能带(),函数带上()表示执行函数 ...
- [笨木头FireFly 02]入门篇2_客户端发送请求,服务器处理请求
原地址:http://www.9miao.com/question-15-53940.html 好,经过上一篇不权威的讲解,大家已经能轻易地让客户端和服务端连接起来了. 但是,仅仅是连接了,可它们俩不 ...
- 前阿里CEO卫哲谈阿里创业经验:如何找人、找钱、找方向?(不同的阶段分别有:时间优先、金额优先、比例优先,不要做平台,太难)
新浪科技李根 整理报道 卫哲现在是御嘉基金的创始合伙人,他另一个更加知名的身份是阿里巴巴(B2B)前CEO,在2006年到2011年的时间里,卫哲见证了阿里巴巴如何利用人才.资本和方向选择一路壮大. ...
- 程序猿接私活经验总结,来自csdn论坛语录
下面为网上摘录,以做笔记: 但是到网上看看,似乎接私活也有非常多不easy,技术问题本身是个因素,还有非常多有技术的人接私活时被骗,或者是合作到最后以失败告终,所以想请有经验的大侠们出来指点一下,接私 ...
- iOS RunTime你知道了总得用一下
说点题外话: 我刚来现在这家公司的时候,老板让我下载一个脉脉,上去找找自己的同行,多认识些同行.其实初衷的好的,但最近这两天我把它卸载了,不为别的,负能量太多!iOS这行自从2016就没景气过,在这行 ...
随机推荐
- WPF数据双向绑定
设置双向绑定,首先控件要绑定的对象要先继承一个接口: INotifyPropertyChanged 然后对应被绑定的属性增加代码如下: 意思就是当Age这个属性变化时,要通知监听它变化的人. 即:Pr ...
- Ruby求出数组中最小值及其下标
其实很简单 Ruby的Array类自带了min方法可以求出最小值,然后调用Array的index方法传入元素值就可以求出下标 a = [1, 2, 3, 4, 5, 6] theMin = a.min ...
- EMVTag系列7《静态签名数据》
Ø 5F24 应用有效期 L: 3 -M(必备) 1) 芯片中的应用失效日期5F24,服务码5F30,必须与芯片中的二磁道等效数据(Tag57)中的失效日期和服务码一致. 2) qPBOC ...
- VPN错误800、错误789
VPN突然无法连接解决方法: 1. 单击“开始”,单击“运行”,键入“regedit”,然后单击“确定” 2. 找到下面的注册表子项,然后单击它:HKEY_LOCAL_MACHINE\System\C ...
- Android--启动系统的剪切图像功能并返回结果
直接上代码: //启动裁剪图片 private void cropPhotoUri(Uri uri){ Intent intent = new Intent("com.android.cam ...
- Java使用FileLock实现Java进程互斥锁
原理:JDK的nio包中FileLock实现类似Linux fcntl的文件锁, 可使文件被进程互斥访问. 借助此功能, 可以实现强大的Java进程互斥锁, 从而在应用层面保证同一时间只有惟一的Ja ...
- sharepoint 2010 切换域
前提: 现在已经有一个sharepoint 2010的环境,当前域为contosoA.com,有个需求需要将这个域切换到域contosoB.com.下面是成功操作的步骤. 1.数据最重要 备份所有数据 ...
- Lisp使用Lambda语法
lamdba 其实就是一个匿名函数. 定义Lisp的lambda语法非常的简单,如下: (lambda ([parameter]) [experssion]) 调用lambda的语法有三种方法,如下: ...
- 容器适配器之queue
转载http://blog.csdn.net/thefutureisour/article/details/7751846容器适配器容器适配器其实就是一个接口转换装置,使得我们能用特定的方法去操作一些 ...
- Netsharp快速入门(之4) 基础档案(之C 实体建模 计量单位、商品、往来单位)
作者:秋时 杨昶 时间:2014-02-15 转载须说明出处 3.3.2 基础档案建模 1.在基础档案项目,右击,选择新建包, 2.录入包的名称,录入名称.完成后点确定 3.3.2.1 计量 ...