最高的广告牌

一、题目描述

题目链接:https://leetcode-cn.com/problems/tallest-billboard/

 

二、题目分析

本题被力扣归为动态规划,无奈本人水平实在有限,最终只能用搜索+剪枝解决。

首先我们有一个最直观的想法,广告牌有left和right两根柱子,对于题目给的钢筋,我们可以选择放在左边,可以可选择放在右边,也可以选择都不放。由此我们便有了回溯的一个基本思想。

然而若我们不对直接进行回溯而不剪枝,是过不了的。因此我们要考虑剪枝的条件。我们将左边的钢筋高度(累计)记为left,右边的钢筋高度(累计)记为right,再使用一个int类型的remain来记录剩余的钢筋的累计和,使用一个ans来记录当前广告牌可达到的最大值。当我们遇到以下两种情况其实就可以返回了。

1、abs(left - right)> remain,即就算剩下的所有的钢筋给短的那边也不够高度。

2、left + right + remain <= 2 * ans,即就算加上remain之后left == right,我们也抛弃,因为左边三者的总和的一半也比当前可达到的最大值小了。

而为了能让我们的剪枝条件生效,我们应该尽量从大的钢筋开始处理。(这里是一个比较直观的想法,并没有进行证明,若由大佬知道如何证明还望评论区指教)

 

三、代码

    private int ans = 0;
    public int tallestBillboard(int[] rods) {
        int len = rods.length;
        if (len == 0 || len == 1) return 0;
        // 计算钢筋的总和
        int remain = 0;
        for (int i: rods) {
            remain += i;
        }
        Arrays.sort(rods);
        // 从最大的钢筋开始处理
        billBoardHelper(rods,rods.length-1,remain,0,0);
        return ans;
    }

    private void billBoardHelper(int[] rods, int i, int remain, int left, int right) {
        // 若左右相等,则进行比较
        if (left == right && left > ans) {
            ans = left;
        }
        // 剪枝
        if (Math.abs(left - right) > remain || left + right + remain <= ans * 2 || i < 0) return;
        // 开始对第i根钢筋进行处理,remain减去rods[i]
        remain -= rods[i];
        // 放左边
        billBoardHelper(rods,i-1,remain,left + rods[i],right);
        // 放右边
        billBoardHelper(rods,i-1,remain,left,right + rods[i]);
        // 不放
        billBoardHelper(rods,i-1,remain,left,right);
    }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值