持续创作,加速成长!这是我参与「掘金日新计划 · 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);
}
由暴力递归改动态规划,自行实现,太简单了。一切从尝试入手,递归的都憋出来了,改成动态规划那是水到渠成的事。