簡體   English   中英

兩人硬幣游戲:動態規划中的最優序列追蹤

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

兩名玩家輪流選擇外幣之一。 最后,我們計算兩名球員得分之間的差異,假設他們發揮最佳。 例如列表{4,3,2,1},最佳序列將是4,3,2,1。然后我將得到4+2 = 6分,對手4分。 現在我開發了一個算法如下: 在此處輸入圖像描述

我的工作是打印分數,以及索引中的最佳序列。 所以在數組 {4,3,2,1} 中,最佳序列是 0,1,2,3。

最大運行時間和 Memory 不應超過 n^2。 因此,我用自下而上的方法實現了上述算法,這意味着在一個 i*j 表中,根據我的算法,子問題被一一解決,直到唯一的主要問題位於右上角(其中 i = 0 和j = n-1)。 它可以計算分數,但我不知道如何在運行時跟蹤最佳序列,因為當我按子問題計算子問題時,只有分數將被保存並用於下一個問題,而導致最終結果的序列結果,很難追溯。

我嘗試創建 Pairs 或多維 ArrayList 來記錄序列及其對應的 memo[i][j]......好吧,它們工作了,但是所需的 memory 將大於 n^2,這是不允許的在我的任務中。

那么,是否有更好的想法不需要那么多 memory 空間?

任何幫助將不勝感激,干杯!

我的代碼:

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];
}

我猜您的問題類似於預測 LeetCode 的獲勝者 (486) ,但您需要進行一些小改動:

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

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

對於此鏈接中提供的第二個解決方案,空間復雜度可能是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;
    }
}

參考

最優化的解決方案都在討論區

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM