华为机试:叠积木

【编程题目 | 100分】叠积木 [ 100 / 中等 ]

叠积木
题目描述

给出一个列表如[[6,7,],[5,4],[3,2]],表示木块的长和宽,当木块的长和宽不大于另个木块的长和宽时,就可以放在上面,此外数组还可以左右翻转。求最多能搭多少层。

输入描述

一个二维数组,里面是每个积木的长和宽,可以左右翻转。

输出描述

最多能搭多少层。

样例
输入
[[5,4],[6,3],[6,7],[6,6],[4,6]]
输出
4
思路分析
  1. 首先对输入的积木进行处理,统一大的做长放第一个位置,小的做宽放第二个位置。

  2. 自定义排序,所有积木降序排,长度降序,相同则宽度降序。

  3. 动态规划求最大。定义一个 dp 数组,dp[i] 表示如果积木为 i 时,最大积木层数。j 表示前 i - 1 个积木,如果前 i - 1 个积木中宽度大于当前积木,dp[i]就等于两者最大值,则状态转移方程:

    if (nums[j][1] >= nums[i][1]) {
        dp[i] = Math.max(dp[i], dp[j] + 1);  // 当前值,或从0到i-1中找到宽大于当前积木的
    }
    
参考代码:
import java.util.Arrays;
import java.util.Scanner;

public class dieJiMu {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String str = in.nextLine();
        // 去掉字符串的所有括号,这里注意下字符串的解析
        str = str.replaceAll("\\[", "");
        str = str.replaceAll("\\]", "");
//        str = str.replaceAll("\\s+", "");  // 去掉所有空格
        String[] str1 = str.split(",");
        int[][] nums = new int[str1.length / 2][2];
        for (int i = 0; i < nums.length; i++) {
            int num1 = Integer.parseInt(str1[2 * i]);
            int num2 = Integer.parseInt(str1[2 * i + 1]);
            nums[i][0] = Math.max(num1, num2);  // 大的为长度
            nums[i][1] = Math.min(num1, num2);  // 小的为宽度
        }
        // 先对积木自定义排序,按长度降序,相同按宽度降序
        Arrays.sort(nums, (o1, o2) -> o1[0] == o2[0] ? o2[1] - o1[1] : o2[0] - o1[0]);
        // 动态规划,dp[i] 表示如果积木为 i 时,最大积木嵌套数
        int[] dp = new int[nums.length];
        Arrays.fill(dp, 1);  // 初始化为1
        int max = 1;
        for (int i = 1; i < nums.length; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[j][1] >= nums[i][1]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);  // 当前值,或从0到i-1中找到宽大于当前积木的
                }
            }
            max = Math.max(dp[i], max);
        }
        System.out.println(max);
    }
}

这类问题如leetcode上的堆箱子,俄罗斯信封套娃问题。

可以参考:【Leetcode】最长递增子序列问题及应用

  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值