---
# System prepended metadata

title: 0956. Tallest Billboard
tags: [Leetcode, Dynamic Programming, Knapsack Problem, Hard]

---

# 0956. Tallest Billboard
###### tags: `Leetcode` `Hard` `Dynamic Programming` `Knapsack Problem`
Link: https://leetcode.com/problems/tallest-billboard/
## 思路
经典背包思想
![](https://i.imgur.com/vrYSDd0.png)
以上解法的最大问题是空间和时间的开销都很大，因为left和right都是```[0,5000]```的区间。空间是$o(5000^2)$，时间则是$o(N*5000^2)$。
优化思想
![](https://i.imgur.com/tJaptzm.png)
注意```maxDiff```不能通过找所有棍子里面最长的和最短的然后相减算出来 这样遇到```[100,100]```就会错 ```maxDiff```应该是```rods```的sum
还要注意初始化```dp``` array的时候不能用0 0间接说明了left stick长度是0 diff是idx 也就是right stick的长度是-idx 这是不合法的

在for回圈里面 我们要用temp复制dp 因为在同一个i里面我们不能更改dp里面的值 这是因为每次更改我们不仅要往前改 还要往后改(通常是只往前改) 所以遍历到后面的时候会被影响到
## Code
```java=
class Solution {
    public int tallestBillboard(int[] rods) {
        int n = rods.length;
        int maxDiff = 5000;
        int[] dp = new int[2*maxDiff+1];
        Arrays.fill(dp, -1);
        dp[maxDiff] = 0;
        for(int i=1; i<=n; i++){
            int[] temp = dp.clone();
            for(int d=-maxDiff; d<=maxDiff; d++){
                if(Math.abs(d+rods[i-1])<=maxDiff && temp[d+rods[i-1]+maxDiff]!=-1) dp[d+maxDiff] = Math.max(dp[d+maxDiff], temp[d+rods[i-1]+maxDiff]);
                if(Math.abs(d-rods[i-1])<=maxDiff && temp[d-rods[i-1]+maxDiff]!=-1) dp[d+maxDiff] = Math.max(dp[d+maxDiff], temp[d-rods[i-1]+maxDiff]+rods[i-1]);
            }
        }
        return dp[maxDiff]==-1?0:dp[maxDiff];
    }
}
```