题目
分析
题目如果用暴力求解的话会超时,暴力求解也就是每个数字有三种状态,不被选中/被选中在左边集合/被选中在右边集合,然后找左右集合相加和最大的那种情况。时间复杂度3的n次方。
题目提示是动态规划题,那么最重要的就是定义状态,差点儿把我愁坏了,然后看了解题报告。
题目求广告牌的最大可能安装高度,那定义 dp[i][j] 来表示 前 i 个支架高度差为 j 的时候,最长的公共长度。
每多添加一个支架,则这个支架其实有三个状态,1.这个支架不添加到任何一端;2.支架添加到高的一端;3.支架添加到短的一端。
- 支架不添加到任何一端 :
这种情况下的 dp[i][j] = dp[i-1][j] 因为第 i 个不用,所以它的最优的公共长度应该 = max( dp[i-1][j], dp[i][j] ) - 支架添加到高的一端
这种情况下即,高的更高, dp[i][j+h] = max(dp[i][j+h] , dp[i][j] + h) - 支架添加到短的一端
这种情况则是把新加进来的支架加到短的一端,也就是加长了短一端的长度,这个时候还会有两种情况,要么是短的加了一截还是短,另一种是短的加了一截变长了。把这两种情况合并一下:即
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];
}
}