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的更多相关文章

  1. 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个石子之后都是必胜,则当前必败 ...

  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 ...

  3. 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 ...

  4. [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 ...

  5. 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 ...

  6. LintCode "Coins in a Line II" !

    Nice one to learn: DP + Game Theoryhttps://lefttree.gitbooks.io/leetcode/content/dynamicProgramming2 ...

  7. 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 ...

  8. [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, ...

  9. LintCode: coins in a line I

    有 n 个硬币排成一条线.两个参赛者轮流从右边依次拿走 1 或 2 个硬币,直到没有硬币为止.拿到最后一枚硬币的人获胜. 请判定 第一个玩家 是输还是赢? n = 1, 返回 true.n = 2, ...

随机推荐

  1. css3动画使用技巧之——transform-delay为负值时的应用。

    <html>    <head>        <title>css3动画delay为负值时的效果</title>        <meta ch ...

  2. JavaScript学习总结【11】、JS 运动

    动画效果在网站中是一种非常常见的交互式体验效果,比如侧边栏分享.图片淡入淡出,我们把这种动画效果就叫做运动,也就是让物体动起来.如果想让一个物体动起来,无非就是改变它的速度,也就是改变属性值,比如 l ...

  3. DIV+CSS 网页布局之:三列布局

    1.宽度自适应三列布局 三列布局的原理和两列布局的原理是一样的,只不过多了一列,只需给宽度自适应两列布局中间再加一列,然后重新计算三列的宽度,就实现了宽度自适应的三列布局. 同样的道理,更多列的布局, ...

  4. JBPM4 常用表结构及其说明

    本文从表结构.操作时表的变化以及jbpm4.4各个包的作用来介绍jbpm的. 第一部分:表结构说明 Jbpm4 共有18张表,如下,其中红色的表为经常使用的表   一:资源库与运行时表结构 1.  J ...

  5. JavaScript模块化开发实例

    最近接触了一些JavaScript开发的例子,在这里与大家一起分享一下: 例子:当我们一个团队在写Js文件的时候,你一个人写的JS代码自己可以看懂也可以维护,但是别人想对你的JS进行扩展的话,如果都在 ...

  6. 多目标遗传算法 ------ NSGA-II (部分源码解析)状态报告 打印 report.c

    /* Routines for storing population data into files */ # include <stdio.h> # include <stdlib ...

  7. Ajax编程相对路径与绝对路径

    http://www.worlduc.com/blog2012.aspx?bid=16946309 ajax同一域名调用采用相对路径 var url = 'QuerySingleDataByField ...

  8. bzoj 2806: [Ctsc2012]Cheat 后缀自动机DP

    2806: [Ctsc2012]Cheat Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 583  Solved: 330[Submit][Statu ...

  9. Session里的对象是不可靠的!

    最近在做Database课程的final project,foodiePharos, 重新认识了JSP里容易出现的一些问题. 比如我们这个项目使用了JPA,就涉及到entity对象的状态问题,Enti ...

  10. [原博客] POJ 2484 A Funny Game

    题目链接题意:有n个硬币排成一圈,两个人轮流操作,每次可以取走一个或者相邻的连个硬币(只算最开始相邻的,取之后才相邻的不算),问先手必胜还是必败. 这个题可以证明若n>=3,则先手必败.对称博弈 ...