简体   繁体   中英

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

The maximum Runtime and Memory should not exceed 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). 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.

So, does anymore have a better idea that does not require that much memory space?

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:

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

The space complexity might be an order of N for the second solution provided in this link :

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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