简体   繁体   English

两人硬币游戏:动态规划中的最优序列追踪

[英]Two player coin game : tracing optimal sequence in dynamic programming

Two players take turns choosing one of the outer coins.两名玩家轮流选择外币之一。 At the end we calculate the difference between the score two players get, given that they play optimally.最后,我们计算两名球员得分之间的差异,假设他们发挥最佳。 for example the list{4,3,2,1}, the optimal sequence would be 4, 3, 2, 1. then i will get 4+2 = 6 scores and the opponent 4 scores.例如列表{4,3,2,1},最佳序列将是4,3,2,1。然后我将得到4+2 = 6分,对手4分。 Now i have developed an algorithm as follow:现在我开发了一个算法如下: 在此处输入图像描述

My Job is to print the scores out, and also the optimal sequence in index.我的工作是打印分数,以及索引中的最佳序列。 so in the array {4,3,2,1} the optimal sequence would be 0,1,2,3.所以在数组 {4,3,2,1} 中,最佳序列是 0,1,2,3。

The maximum Runtime and Memory should not exceed n^2.最大运行时间和 Memory 不应超过 n^2。 Therefore I implemented the above algorithm with bottom up approach,which means in an i*j table, according to my algorithm, subproblems are solved one by one until the only main problem, which locates at the top right corner(where i =0 and j = n-1).因此,我用自下而上的方法实现了上述算法,这意味着在一个 i*j 表中,根据我的算法,子问题被一一解决,直到唯一的主要问题位于右上角(其中 i = 0 和j = n-1)。 It works calculating the scores, but i have no idea how to trace the optimal sequence during runtime, since when I calculate subproblems by subproblems, only the score will be save and used in the next problem, while the sequence, which led to the final result, is hard to trace back.它可以计算分数,但我不知道如何在运行时跟踪最佳序列,因为当我按子问题计算子问题时,只有分数将被保存并用于下一个问题,而导致最终结果的序列结果,很难追溯。

I tried to create Pairs or multidimensional ArrayList to record the sequences and their corresponding memo[i][j]...... Well, they worked, but the memory needed would then be greater than n^2 and this is not allowed in my task.我尝试创建 Pairs 或多维 ArrayList 来记录序列及其对应的 memo[i][j]......好吧,它们工作了,但是所需的 memory 将大于 n^2,这是不允许的在我的任务中。

So, does anymore have a better idea that does not require that much memory space?那么,是否有更好的想法不需要那么多 memory 空间?

Any help would be appreciated, cheers!任何帮助将不胜感激,干杯!

My code:我的代码:

public int maxGain(int[] values) {

    int n = values.length;
    int [][] memo = new int[n][n];

    for (int i = 0; i < n; i++)
        memo[i][i] = values[i];

    for (int i = 0, j = 1; j < n; i++, j++)
        memo[i][j] = Math.max(values[i], values[j]);

    for (int k = 2; k < n; k++) {
        for (int i = 0,  j = k; j < n; i++, j++) {
            int a = values[i] + Math.min(memo[i + 2][j], memo[i + 1][j - 1]);
            int b = values[j] + Math.min(memo[i + 1][j - 1], memo[i][j - 2]);
            memo[i][j] = Math.max(a, b);
        }
    }

    return memo[0][n - 1];
}

I guess your question is similar to Predict the Winner of LeetCode (486) with some minor changes that you would want to make:我猜您的问题类似于预测 LeetCode 的获胜者 (486) ,但您需要进行一些小改动:

Java Java

class Solution {
    public boolean maxGain(int[] nums) {
        int length = nums.length;
        int[][] dp = new int[length][length];

        for (int i = 0; i < length; i++)
            dp[i][i] = nums[i];

        for (int l = 1; l < length; l++)
            for (int i = 0; i < length - l; i++) {
                int j = i + l;
                dp[i][j] = Math.max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1]);
            }

        return dp[0][length - 1] > -1;
    }
}

Python Python

class Solution:
    def max_gain(self, nums):
        length = len(nums)
        memo = [[-1 for _ in range(length)] for _ in range(length)]

        @functools.lru_cache(None)
        def f():
            def helper(nums, i, j):
                if i > j:
                    return 0

                if i == j:
                    return nums[i]

                if memo[i][j] != -1:
                    return memo[i][j]

                cur = max(nums[i] + min(helper(nums, i + 2, j), helper(nums, i + 1, j - 1)),
                          nums[j] + min(helper(nums, i, j - 2), helper(nums, i + 1, j - 1)))

                memo[i][j] = cur
                return cur

            score = helper(nums, 0, length - 1)
            total = sum(nums)
            return 2 * score >= total

        return f()

O(N) Memory O(N) Memory

The space complexity might be an order of N for the second solution provided in this link :对于此链接中提供的第二个解决方案,空间复杂度可能是N的数量级:

class Solution {
    public boolean maxGain(int[] nums) {
        if (nums == null)
            return true;

        int length = nums.length;
        int[] dp = new int[length];

        for (int i = length - 1; i >= 0; i--) {
            for (int j = i; j < length; j++) {
                if (i == j)
                    dp[i] = nums[i];

                else
                    dp[j] = Math.max(nums[i] - dp[j], nums[j] - dp[j - 1]);
            }
        }

        return dp[length - 1] > -1;
    }
}

Reference参考

Most optimal solutions are here in the discussion board 最优化的解决方案都在讨论区

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM