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就没景气过,在这行 ...
随机推荐
- 刀哥多线程之主队列gcd-06-main_queue
主队列 特点 专门用来在主线程上调度任务的队列 不会开启线程 以先进先出的方式,在主线程空闲时才会调度队列中的任务在主线程执行 如果当前主线程正在有任务执行,那么无论主队列中当前被添加了什么任务,都不 ...
- C,C++容易被忽略的问题
1.字符串数组,字符串指针可以直接输出 ]="I am a student"; cout<<s2<<endl; char *p="I am a s ...
- Java 控制台执行带自定义包定义的类,出现“Exception in thread "main" java.lang.NoClassDefFoundError: ConnectSQLServer (wrong name: sine/ConnectSQLServer)”
1.先说明一下代码实现:自定义package sine, 源代码保存路径为:E:\JSP\HibernateDemo\HibernateDemoProject\src\sine\ConnectSQLS ...
- linux下更改文件夹所属用户和用户组
改变所属用户组:chgrp -R users filename -R是为了递归改变文件夹下的文件和文件夹,users是要改为的用户组名称,filename是要改变的文件夹名称 ============ ...
- Jni中C++和Java的参数传递
Jni中C++和Java的参数传递 如何使用JNI的一些基本方法和过程在网上多如牛毛,如果你对Jni不甚了解,不知道Jni是做什么的,如何建立一个基本的jni程序,或许可以参考下面下面这些文章:利用V ...
- Objective-C 编码规范
Objective-C 编码规范,内容来自苹果.谷歌的文档翻译,自己的编码经验和对其它资料的总结. 概要 Objective-C 是一门面向对象的动态编程语言,主要用于编写 iOS 和 Mac 应用程 ...
- MVC4.0 利用IActionFilter实现简单的后台操作日志功能
首先我们要了解MVC提供了4种常用的拦截器:IActionFilter(Action拦截器接口).IExceptionFilter(异常拦截器接口).IResultFilter(Result拦截器接口 ...
- 可综合风格的VerilogHDL模块实例
1.赋值语句:assign{cout,sum}=a+b+cin; 2.利用电平敏感的always块设计组合逻辑电路 3.always块中如果含有局部变量,就必须在begin后加模块名,是必须加,同样的 ...
- C# 非独占延时函数 非Sleep
在C#窗口程序中,如果在主线程里调用Sleep,在Sleep完成之前, 界面呈现出假死状态,不能响应任何操作! 下边实现的是非独占性延时函数,延时过时中界面仍可响应消息: public static ...
- fstream对象重复使用时注意clear()的调用
fstream对象重复使用时注意clear()的调用,否则会造成打开第二个文件失败.这是因为一个fstream对象对应磁盘上的一个文件,这种绑定关系在调用open()函数或者构造函数时指定,但有时我们 ...