动态规划-01背包-Tallest Billboard

Posted hyserendipity

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划-01背包-Tallest Billboard相关的知识,希望对你有一定的参考价值。

2020-02-07 17:46:32

问题描述:

技术图片

技术图片

问题求解:

解法一:BF

看问题规模看似可以直接暴力解决。

如果直接去解肯定是会超时的,因为每次将原空间划分成A区域,B区域和剩余区域的时间复杂度为O(3 ^ n)。

但是我们可以将问题进行一下转化,之前有个问题是能否将一个数组中的数划分成两个和相等的子区域那个题目是可以使用dp完成求解的,时间复杂度是O(nsum)。

因此我们可以去构造出所有的挑选可能,并对每个可能产生解的可能去过一遍dp就能完成本题。

但是,本解法并不是最优解。

    int ret = 0;
    int[] nums;
    List<Integer> res = new ArrayList<>();
    
    public int tallestBillboard(int[] rods) {
        nums = rods;
        helper(0, 0);
        return ret;
    }
    
    private void helper(int start, int sum) {
        if (start >= nums.length) return;
        if (sum % 2 == 0 && check(res, sum / 2)) {
            ret = sum / 2;
        }
        helper(start + 1, sum);
        res.add(nums[start]);
        sum += nums[start];
        if (sum % 2 == 0 && check(res, sum / 2)) {
            ret = sum / 2;
        }
        helper(start + 1, sum);
        sum -= nums[start];
        res.remove(res.size() - 1);
    }
    
    private boolean check(List<Integer> nums, int target) {
        if (target <= ret) return false;
        int[] dp = new int[target + 1];
        dp[0] = 1;
        for (int num : nums) {
            for (int w = target; w >= num; w--) {
                dp[w] |= dp[w - num];
            }
        }
        return dp[target] == 1;
    }

解法二:DP

事实上,本题可以直接使用dp求解。时间复杂度O(nSum),但是状态的定义有点特殊。

dp[i][j] : 取前i个数字,diff = j的最大公共区域。

dp[0][0] = 0, dp[i][j] = -inf

    int inf = (int)1e9;
    public int tallestBillboard(int[] rods) {
        int n = rods.length;
        int sum = 0;
        for (int num : rods) sum += num;
        int[][] dp = new int[n + 1][sum + 1];
        for (int i = 0; i <= n; i++) Arrays.fill(dp[i], -inf);
        dp[0][0] = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j <= sum - rods[i - 1]; j++) {
                // not use i
                dp[i][j] = Math.max(dp[i][j], dp[i - 1][j]);
                // put on higher part
                dp[i][j + rods[i - 1]] = Math.max(dp[i][j + rods[i - 1]], dp[i - 1][j]);
                // put on lower part
                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[n][0];
    }

  

 

以上是关于动态规划-01背包-Tallest Billboard的主要内容,如果未能解决你的问题,请参考以下文章

求动态规划0-1背包算法解释

动态规划 -- 01背包问题和完全背包问题

动态规划_01背包_完全背包_多重背包_分组背包

急!动态规划 多人背包问题

算法之名——动态规划(01背包)

动态规划——背包问题python实现(01背包完全背包多重背包)