内卷大厂系列《动态规划-要还是不要模型》

105 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

《动态规划练习-要还是不要模型》,您将学到如何利用暴力递归改动态规划,一切从尝试入手,如何定义递归函数的含义也是有套路的,模型就是要还是不要,选还是不选的问题上做文章。

一、题目一

一根绳子总长度为M,绳子可以切成任意长度的绳子,每一个长度的绳子对应一个价格,比如(6,10)表示剪成长度为6的绳子,对应的价格为10元,可以重复的切出某个长度的绳子。

规定所有可以切出来的长度对应的价值都在数组ropes里,ropes[i] = {6,10} 代表i方案为切出长度为6的绳子,可以卖10元。在所有切出来的绳子价值中,返回最大价值。

1、分析

arr[i][0] i号方案能且多少长度

arr[i][1] 切出来这个长度,就能获取的价值

arr[index...] 自由选择,绳子还剩restLen长度

返回最大价值

2、实现

暴力递归

public static int maxValue(int[][] ropes, int M) {
    return process(ropes, 0, M);
}

public static int process(int[][] arr, int index, int restLen) {
    if (restLen <= 0 || index == arr.length) { // base case
        return 0;
    }
    // 绳子还有剩余、且还有方案
    // index号方案
    // 不选
    int p1 = process(arr, index + 1, restLen);
    // 选
    int p2 = 0;
    if (arr[index][0] <= restLen) { // 剩余绳子够长,才能选当前方案
        p2 = arr[index][1] + process(arr, index, restLen - arr[index][0]);
    }
    return Math.max(p1, p2);
}

由暴力递归改动态规划,自行实现,太简单了。一切从尝试入手,递归的都憋出来了,改成动态规划那是水到渠成的事。

二、题目二

有一组序列,每一个序列都是[a,b]的形式,a的值小于b的值,而且序列的连接方式为,前一个序列的b,要等于后一个序列的a

比如:[3,7]、[7,13]、[13,26]这三个序列就可以依次连接

给定若干序列,求最大连接的数量

1、分析

arr[i] = {4,9}表示第i个序列从4开始,9结束,preIndex代表选择的上一个序列的index是多少。

定义递归函数的含义:arr[index...]所有的序列,随便选择,index之前的序列,已经选好了,不用管,上一个选择的序列是preIndex,如果preIndex=-1,说明之前没有选择过序列,arr[index...]能链接起来的,返回序列数量的最大值

2、实现

暴力递归

public static int maxLen(int[][] arr, int index, int preIndex) {
    if (index == arr.length) { // base case
        return 0;
    }
    // 还有序列可以选
    // index号序列
    // 不选
    int p1 = maxLen(arr, index + 1, preIndex);
    // 选
    int p2 = 0;
    // [3,17] index(9,24)
    if (arr[preIndex][1] == arr[index][0]) { // 才能选
        p2 = 1 + maxLen(arr, index + 1, index);
    }
    return Math.max(p1, p2);
}

由暴力递归改动态规划,自行实现,太简单了。一切从尝试入手,递归的都憋出来了,改成动态规划那是水到渠成的事。