395. Coins in a Line II
刷
July-31-2019
这种题遇到就两腿一蹬,地上一躺。 和coins-in-a-line-I除了名字很像,没啥屌关系,如果真的作为I的follow up,就太坑了,因为根本不是FOLLOW UP,用1的思路去考虑就崩了。
dp[n]代表剩下n个硬币的时候的最大收益。
n的时候,有2种情况,可以选择拿1个,也可以选择拿2个:
- 拿1个,然后对方会选择拿1个或者拿2个, 此时我的收益就是:
- 当前1个硬币价值 + 剩n-2个 和 剩n-3个中较小的一个,因为分别对应对方拿1个或者2个,而对方他妈又不是傻逼,会选择1个或者2个中收益多的
- 拿2个,然后对方会选择拿1个或者拿2个,此时我的收益就是:
- 当前2个硬币的价值 + 剩n-3和n-4中较小的。
dp[n]是上面2种情况中拿1个或者拿2个收益高的
这种题做的太少,不好总结。
一开始的012是为了防止出现只有1个硬币却尝试拿2个的情况。
仔细看会发现dp[n-1]永远没被用过,也很诡异。
public class Solution {
public boolean firstWillWin(int[] values) {
// write your code here
if (values == null) return false;
if (values.length <= 2) return true;
int total = values.length;
// dp[X] x coins left
int[] dp = new int[total + 1];
Arrays.fill(dp, -1);
dp[0] = 0;
dp[1] = values[total-1];
dp[2] = values[total-1] + values[total-2];
dp[total] = getProfit(total, dp, values);
int valueCount = 0;
for (int i : values) valueCount += i;
return dp[total] * 2 > valueCount;
}
public int getProfit(int remain, int[] dp, int[] values) {
if (remain <= 0) return 0;
if (dp[remain] != -1) return dp[remain];
int coinCount = values.length;
// pick 1, the other people will choose max from pick next 1 or next 2
// which leaves us min from pick 1
int pickOne = values[coinCount - remain]
+ Math.min(getProfit(remain-1-1, dp, values),
getProfit(remain-1-2, dp, values));
int pickTwo = values[coinCount - remain] + values[coinCount - remain + 1]
+ Math.min(getProfit(remain-2-1, dp, values),
getProfit(remain-2-2, dp, values));
dp[remain] = Math.max(pickOne, pickTwo);
return dp[remain];
}
}
最后更新
2016-12-22
这个题做得也不好,dp[n]尝试写了几下,不太对。
应该是类似于gem theory的题。
当只有1个硬币剩下的时候直接拿走,不BB。
剩俩的时候也都拿了。。
dp[n]表示剩下多少个硬币。
轮到我们拿第i个硬币的时候,有2种情况:
- 我们拿这个 i 。
- 对手选择拿1个,就是第i+1个,然后第i+ 2轮到我们,我们再决定。
- 对手选择拿2个,i+1和i+2, 然后i+3轮到我们。
- 我们拿这个i,再拿下一个i+1。
- 对手选择拿1个,就是第i+2, 然后i+3轮到我们。
- 对手选择拿2个,i+2, i+3,然后i+4该我们选择了。
当前怎么选取决于拿1个得的多还是拿2个得的多:
dp[i] = Math.max(拿1个, 拿2个)
但是注意中间对手拿的时候,他也要选择对他有利的,所以再轮到我们的时候,我们就拿得相对小的那个选择。
拿1个 = 当前的1个硬币 + Math.min(第i+2轮到我们,第i+3轮到我们)
拿2个 = 当前的2个硬币 + Math.min(第i+3轮到我们, 第i+4轮到我们)
思路很绕,是一个极小极大的思路,minimax。
另一个地方是并没有急于计算对手能拿多少而减去他的决定,而是尝试在他的选择下直接获取我们的硬币,最后看看拿的数量过不过半。
一头雾水。。。
public class Solution {
public boolean firstWillWin(int[] values) {
if (values.length <= 2) return true;
// max profit when there are n coins left
int[] dp = new int[values.length + 1];
Arrays.fill(dp, -1);
int total = values.length;
dp[0] = 0;
// only 1 left, we get that one
dp[1] = values[total-1];
// only 2 left, we grab those 2 fucking coins
dp[2] = values[total-2] + values[total-1];
// wat will we get when there are n left..
dp[total] = nthProfit(total, dp, values);
int sum = 0;
for (int i : values) sum += i;
return dp[total] > sum/2;
}
public int nthProfit(int leftOver, int[] dp, int[] values) {
if (leftOver <= 0) return 0;
if (dp[leftOver] != -1) return dp[leftOver];
int total = values.length;
int pickOne = values[total - leftOver] +
Math.min(nthProfit(leftOver-2, dp, values),
nthProfit(leftOver-3, dp, values));
int pickTwo = values[total - leftOver] + values[total - leftOver + 1] +
Math.min(nthProfit(leftOver-3, dp, values),
nthProfit(leftOver-4, dp, values));
dp[leftOver] = Math.max(pickOne, pickTwo);
return dp[leftOver];
}
}
395. Coins in a Line II的更多相关文章
- lintcode 394. Coins in a Line 、leetcode 292. Nim Game 、lintcode 395. Coins in a Line II
变型:如果是最后拿走所有石子那个人输,则f[0] = true 394. Coins in a Line dp[n]表示n个石子,先手的人,是必胜还是必输.拿1个石子,2个石子之后都是必胜,则当前必败 ...
- [LintCode] Coins in a Line II 一条线上的硬币之二
There are n coins with different value in a line. Two players take turns to take one or two coins fr ...
- Lintcode395 Coins in a Line II solution 题解
[题目描述] There are n coins with different value in a line. Two players take turns to take one or two c ...
- [LintCode] 395. Coins in a Line 2_Medium tag: Dynamic Programming, 博弈
Description There are n coins with different value in a line. Two players take turns to take one or ...
- Coins in a Line II
There are n coins with different value in a line. Two players take turns to take one or two coins fr ...
- LintCode "Coins in a Line II" !
Nice one to learn: DP + Game Theoryhttps://lefttree.gitbooks.io/leetcode/content/dynamicProgramming2 ...
- Coins in a Line I & II
Coins in a Line I There are n coins in a line. Two players take turns to take one or two coins from ...
- [LeetCode] 877. Stone Game == [LintCode] 396. Coins in a Line 3_hard tag: 区间Dynamic Programming, 博弈
Alex and Lee play a game with piles of stones. There are an even number of piles arranged in a row, ...
- LintCode: coins in a line I
有 n 个硬币排成一条线.两个参赛者轮流从右边依次拿走 1 或 2 个硬币,直到没有硬币为止.拿到最后一枚硬币的人获胜. 请判定 第一个玩家 是输还是赢? n = 1, 返回 true.n = 2, ...
随机推荐
- php 简单的验证码
注意事项: 验证的隐藏域的位置一定要在调用JS前.. 如: <input type="text" name="yzm" value="" ...
- SVG绘制圆形简单示例分享
今天分享“svg绘制圆形”部分 1.简单圆形 效果图如下: 关键代码: <svg xmlns="http://www.w3.org/2000/svg" version=&qu ...
- php中引用符号(&)的使用详解
php的引用就是在变量或者函数.对象等前面加上&符号,在PHP 中引用的意思是:不同的名字访问同一个变量内容,下面介绍如何使用PHP的引用 与C语言中的指针是有差别的.C语言中的指针里面存储的 ...
- 4种方法生成二维码 (js 控制canvas 画出 二维码)
随着网络的迅速发展 发展 发展,二维码的应用将会越来越多.同时很多只是很平凡的二维码,请拿起你的手 把这个二维码 设计起来吧.下面分享了几个非常好的二维码设计. 二维码原理: 二维条码/二维码可以分 ...
- [简历] PHP 技能关键字列表
本技能关键字列表是从最近招聘PHP的数百份JD中统计出来的,括号中是出现的词频.如果你的简历要投递给有机器(简历分选系统)和不如机器(不懂技术的HR)筛选简历环节的地方,请一定从下边高频关键词中选择5 ...
- ubuntu杂记
安装ssh: sudo apt-get install openssh-server sudo /etc/init.d/ssh start 将主机中vmware8的网络改为自动获取ip,就可以ping ...
- STM32系统时钟
一.时钟树 STM32有4个时钟源: 1)HSE(高速外部时钟源) 外部晶振作为时钟源,范围为4~16MHz,常取为8MHz 2)HSI(高速内部时钟源) 由内部RC振荡器产生,频率为8MHz,但不稳 ...
- 查找类class所在的jar包
CTRL+SHIFT+R 意思是输入关键字搜索当前工程的 对象. CTRL+SHIFT+T 输入关键字搜索当前工程的类.
- nump中的为随机数产生器的seed
在python的程序中,发现了如下的伪随机数产生的代码 rng = numpy.random.RandomState(23355) arrayA = rng.uniform(0,1,(2,3)) 该段 ...
- IP工具类——IpAddress.java
根据IP地址获取详细的地域信息,也可通过 http://whois.pconline.com.cn/ 获取地址信息. 源码如下:(点击下载 IpAddress.java) import java.i ...