zoukankan      html  css  js  c++  java
  • Line of wines

    There are N wines in a row. Each year you sell either the leftmost or the rightmost wine. The i-th wine has initial price p[i] and price k * p[i] in the k-th year. What is the maximum possible total profit?

    Solution 1. Bottom up dynamic programming

    state:
    dp[i][j]: the max possible profit of wines[i, j] at year i - 0 + N - 1 - j + 1 = N + i - j
    dp[i][j] = max of {p[i] * (N + i - j) + dp[i + 1][j], p[j] * (N + i -j) + dp[i][j - 1]}

    Initialization:
    dp[i][i] = N * p[i]

    Ans:
    dp[0][N - 1]

    Loop over i and j. In this case, the loop order matters. In order to compute dp[i][j], we need to have dp[i + 1][j] and dp[i][j - 1] first. This means we need to loop i in decreasing order from N - 1 to 0 and j in increasing order from i + 1 to N - 1.

        public int maxProfitBottomUp(int[] p) {
            int N = p.length;
            int[][] dp = new int[N][N];
            for(int i = 0; i < N; i++) {
                dp[i][i] = N * p[i];
            }
            for(int i = N - 1; i >= 0; i--) {
                for(int j = i + 1; j < N; j++) {
                    dp[i][j] = Math.max(p[i] * (N + i - j) + dp[i + 1][j], p[j] * (N + i -j) + dp[i][j - 1]);
                }
            }
            return dp[0][N - 1];
        }

    Loop over the interval length first, then loop over all possible left start.

        public int maxProfitBottomUp(int[] p) {
            int N = p.length;
            int[][] dp = new int[N][N];
            for(int i = 0; i < N; i++) {
                dp[i][i] = N * p[i];
            }
            for(int len = 2; len <= N; len++) {
                for(int l = 0; l <= N - len; l++) {
                    int r = l + len - 1;
                    int y = N + l - r;
                    dp[l][r] = Math.max(p[l] * y + dp[l + 1][r], p[r] * y + dp[l][r - 1]);
                }
            }
            return dp[0][N - 1];
        }

    Solution II. Top down dynamic programming

    State:

    dp[l][r]: the max possible profit before we go to interval [l, r].

    dp[l][r] = Math.max(dp[l][r + 1] + p[r + 1] * (currY - 1), dp[l - 1][r] + p[l - 1] * (currY - 1)), currY = N + l - r.


    Initialization:
    dp[0][N - 1] = 0


    Answer:
    max of {dp[i][i] + p[i] * N}

        public int maxProfitTopDown(int[] p) {
            int N = p.length;
            int[][] dp = new int[N][N];
            dp[0][N - 1] = 0;
    
            for(int len = N - 1; len >= 1; len--) {
                for(int l = 0; l + len <= N; l++) {
                    int r = l + len - 1;
                    int currY = N + l - r;
                    if(r < N - 1) {
                        dp[l][r] = Math.max(dp[l][r], dp[l][r + 1] + p[r + 1] * (currY - 1));
                    }
                    if(l > 0) {
                        dp[l][r] = Math.max(dp[l][r], dp[l - 1][r] + p[l - 1] * (currY - 1));
                    }
                }
            }
    
            int res = 0;
            for(int i = 0; i < N; i++) {
                res = Math.max(res, dp[i][i] + p[i] * N);
            }
            return res;
        }

    Solution III. Bottom up dynamic programming with prefix sum 

    Key idea: if we assume every interval starts with year 1 and already have the max profit for interval[l, r - 1] and [l + 1, r], then to compute interval[l, r], we shift all the years for [l, r - 1] and [l + 1, r] by 1, then add either p[r] or p[l]. This is the prefixsum of interval[l, r].

    dp[l][r]: the max possible profit of wines[l, r] starting from year 1.
    dp[l][r] = Math.max(dp[l][r - 1], dp[l + 1][r]) + prefixSum[l, r]

    init: dp[i][i] = 1 * p[i]

    Ans: dp[0][N - 1]

        public int maxProfitPrefixSum(int[] p) {
            int N = p.length;
            int[][] dp = new int[N][N];
            for(int i = 0; i < N; i++) {
                dp[i][i] = p[i];
            }
            int[] prefixSum = new int[N];
            prefixSum[0] = p[0];
            for(int i = 1; i < N; i++) {
                prefixSum[i] = prefixSum[i - 1] + p[i];
            }
            for(int i = N - 1; i >= 0; i--) {
                for(int j = i + 1; j < N; j++) {
                    dp[i][j] = Math.max(dp[i][j - 1], dp[i + 1][j]) + prefixSum[j] - (i > 0 ? prefixSum[i - 1] : 0);
                }
            }
            return dp[0][N - 1];
        }
  • 相关阅读:
    逆向测试设计
    JNLP
    3. 技术专题
    8.2. Angular使用Material控件库
    Spring Boot Actuator
    安装
    apk文件结构及反编译/代码混淆
    Visual Studio中attach进程进行调试
    .NET反编译
    3. 技术专题
  • 原文地址:https://www.cnblogs.com/lz87/p/11518228.html
Copyright © 2011-2022 走看看