1770. Maximum Score from Performing Multiplication Operations

You are given two integer arrays nums and multipliers of size n and m respectively, where n >= m. The arrays are 1-indexed.

You begin with a score of 0. You want to perform exactly m operations. On the ith operation (1-indexed), you will:

  • Choose one integer x from either the start or the end of the array nums.
  • Add multipliers[i] * x to your score.
  • Remove x from the array nums.

Return the maximum score after performing m operations.

 

Example 1:

Input: nums = [1,2,3], multipliers = [3,2,1]
Output: 14
Explanation: An optimal solution is as follows:
- Choose from the end, [1,2,3], adding 3 * 3 = 9 to the score.
- Choose from the end, [1,2], adding 2 * 2 = 4 to the score.
- Choose from the end, [1], adding 1 * 1 = 1 to the score.
The total score is 9 + 4 + 1 = 14.

Example 2:

Input: nums = [-5,-3,-3,-2,7,1], multipliers = [-10,-5,3,4,6]
Output: 102
Explanation: An optimal solution is as follows:
- Choose from the start, [-5,-3,-3,-2,7,1], adding -5 * -10 = 50 to the score.
- Choose from the start, [-3,-3,-2,7,1], adding -3 * -5 = 15 to the score.
- Choose from the start, [-3,-2,7,1], adding -3 * 3 = -9 to the score.
- Choose from the end, [-2,7,1], adding 1 * 4 = 4 to the score.
- Choose from the end, [-2,7], adding 7 * 6 = 42 to the score. 
The total score is 50 + 15 - 9 + 4 + 42 = 102.

 

Constraints:

  • n == nums.length
  • m == multipliers.length
  • 1 <= m <= 103
  • m <= n <= 105
  • -1000 <= nums[i], multipliers[i] <= 1000
class Solution {
    int n, m;
    int[] nums, muls;
    Integer[][][] memo;
    public int maximumScore(int[] nums, int[] muls) {
        n = nums.length;
        m = muls.length;
        this.nums= nums;
        this.muls = muls;
        this.memo = new Integer[m][m][n];
        return dp(0, 0, n - 1);
    }
    private int dp(int l, int i, int r) {
        if (i == m) return 0; // Picked enough m elements
        if (memo[l][i][r] != null) return memo[l][i][r];
        int pickLeft = dp(l+1, i+1, r) + nums[l] * muls[i]; // Pick the left side
        int pickRight = dp(l, i+1, r - 1) + nums[r] * muls[i]; // Pick the right side
        return memo[l][i][r] = Math.max(pickLeft, pickRight);
    }
}

https://leetcode.com/problems/maximum-score-from-performing-multiplication-operations/discuss/1075469/JavaC%2B%2BPython-3-Top-Down-DP-O(m2)-Clean-and-Concise

https://leetcode.com/problems/maximum-score-from-performing-multiplication-operations/discuss/1075492/Java-Detailed-Explanation-DP-Optimize-Space

public int maximumScore(int[] nums, int[] multipliers) {
        
    int N = nums.length, M = multipliers.length;

    return helper(nums, multipliers, 0, N - 1, new Integer[M][M]);
}

private int helper(int[] nums, int[] multipliers, int i, int j, Integer[][] dp) {

    int N = nums.length, M = multipliers.length;
    int index = (i - 0) + (N - 1 - j);
    if (index == M) return 0;

    if (dp[i][j - (N - M)] != null) return dp[i][j - (N - M)];

    int res = Math.max(nums[i] * multipliers[index] + helper(nums, multipliers, i + 1, j, dp), 
                       nums[j] * multipliers[index] + helper(nums, multipliers, i, j - 1, dp));

    return dp[i][j - (N - M)] = res;
}

 这个index咋算的看了好久才反应过来:index,是ith step,是算到了第几步,那么前面的步骤是咋算出来的?要么pick左边,要么右边是不是?通过l和r的位置可以得出当前计算了多少步:(i - 0)是选了几次左边,(N - 1 - j)是选了几次右边,两个之和就是index了。

https://leetcode.com/problems/maximum-score-from-performing-multiplication-operations/discuss/1075697/JAVA-Bottom-Up-DP-O(m2)-Runtime

 

 

public int maximumScore(int[] nums, int[] multipliers) {
        int m = multipliers.length;

        int[][] dp = new int[m+1][m+1];
        dp[0][0] = 0;
        int result = Integer.MIN_VALUE;
        for(int left = 0; left <= m; ++left) {
            for (int right = 0; right <= m; right++) {
                int index = right + left -1;
                if (index < 0 || index >= m)
                    continue;
                
                if (left == 0) {
                    dp[left][right] = dp[left][right -1] + nums[nums.length - right] * multipliers[index];
                } else if (right == 0) {
                    dp[left][right] = dp[left -1][right] + nums[left -1] * multipliers[index];
                } else {
                    int a = dp[left -1][right] + nums[left -1] * multipliers[index];
                    int b = dp[left][right -1] + nums[nums.length - right] * multipliers[index];
                    dp[left][right] = Math.max(a, b);
                }
                
                if (index == m-1) {
                    result = Math.max(result, dp[left][right]);
                }
            }
        }
        return result;
    }

 

posted @ 2022-09-16 11:56  Schwifty  阅读(47)  评论(0)    收藏  举报