LeetCode956. 最高的广告牌

题目

LeetCode956. 最高的广告牌_第1张图片

分析

题目如果用暴力求解的话会超时,暴力求解也就是每个数字有三种状态,不被选中/被选中在左边集合/被选中在右边集合,然后找左右集合相加和最大的那种情况。时间复杂度3的n次方。

题目提示是动态规划题,那么最重要的就是定义状态,差点儿把我愁坏了,然后看了解题报告。

题目求广告牌的最大可能安装高度,那定义 dp[i][j] 来表示 前 i 个支架高度差为 j 的时候,最长的公共长度。

每多添加一个支架,则这个支架其实有三个状态,1.这个支架不添加到任何一端;2.支架添加到高的一端;3.支架添加到短的一端。

  1. 支架不添加到任何一端 :
    这种情况下的 dp[i][j] = dp[i-1][j] 因为第 i 个不用,所以它的最优的公共长度应该 = max( dp[i-1][j], dp[i][j] )
  2. 支架添加到高的一端
    这种情况下即,高的更高, dp[i][j+h] = max(dp[i][j+h] , dp[i][j] + h)
  3. 支架添加到短的一端
    这种情况则是把新加进来的支架加到短的一端,也就是加长了短一端的长度,这个时候还会有两种情况,要么是短的加了一截还是短,另一种是短的加了一截变长了。把这两种情况合并一下:即
    dp[i][|j-h|] = max( dp[i][|j-h|] , dp[i-1][j] + min(j, h) )

代码

class Solution {
    public int tallestBillboard(int[] rods) {
        int len = rods.length;
        int[][] dp = new int[len+1][5001];
        for (int i = 0; i < len+1; i++)
            for (int j = 0; j < dp[0].length; j++) dp[i][j] = -5001;
        int sum = 0;
        dp[0][0] = 0;
        for (int i = 1; i <= len; i++) {
            sum += rods[i-1];
            for (int j = 0; j <= sum; j++) {
                dp[i][j] = Math.max(dp[i-1][j],dp[i][j]);
                if (j + rods[i-1] <= sum)
                    dp[i][j+rods[i-1]] = Math.max(dp[i-1][j], dp[i][j+rods[i-1]]);

                dp[i][Math.abs(j-rods[i-1])] = Math.max(dp[i][Math.abs(j-rods[i-1])], dp[i-1][j] + Math.min(j,rods[i-1]));
            }
        }
        return dp[len][0];
    }
}

你可能感兴趣的:(算法)