8.动态规划_01
动态规划
题解来源: 代码随想录
746. 使用最小花费爬楼梯
class Solution {
public int minCostClimbingStairs(int[] cost) {
if (cost == null) {
return 0;
}
int n = cost.length;
if (n == 1) {
return cost[0];
}
// dp[i] 代表上到第i个阶梯所需的最小花费
int[] dp = new int[n];
dp[0] = cost[0];
dp[1] = cost[1];
for (int i = 2 ; i < n; i++) {
// 可以从第 i - 1 或者第 i - 2 步到达阶梯顶
dp[i] = Math.min(dp[i - 1],dp[i - 2]) + cost[i];
}
return Math.min(dp[n - 1], dp[n - 2]);
}
}
343. 整数拆分
public int integerBreak(int n) {
// dp[i] 代表整数 i 拆分后的最大乘积
int[] dp = new int[n + 1];
dp[2] = 1;
for (int i = 3; i <= n; i++) {
// j*(i-j)代表把i拆分为j和i-j两个数相乘
// j*dp[i-j]代表把i拆分成j和继续把(i-j)这个数拆分,取(i-j)拆分结果中的最大乘积与j相乘
for (int j = 1; j < i - 1; j++) {
dp[i] = Math.max(dp[i], Math.max(dp[i - j], i - j) * j);
}
}
return dp[n];
}
背包理论
基础一
public static void main(String[] args) {
int[] weight = {1, 3, 4};
int[] value = {15, 20, 30};
int bagSize = 4;
bag(weight, value, bagSize);
}
public static void bag(int[] weight, int[] value, int bagSize) {
// dp[i][j] 表示背包容量为 j 时,选取 0 - i 个物品装入背包的最大值;
int[][] dp = new int[weight.length][bagSize + 1];
// 背包只装一个物品的初始化
for (int i = weight[0]; i <= bagSize; i++) {
dp[0][i] = value[0];
}
// 顺序遍历物品
for (int i = 1; i < weight.length; i++) {
for (int j = 0; j <= bagSize; j++) {
if (j < weight[i]) { // 当前背包容量不足,装不下物品 i
dp[i][j] = dp[i - 1][j];
} else { // 当前背包容量充足,可以装下物品 i
// 可以选择装,或者不装物品 i
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
}
}
}
for (int i = 0; i < weight.length; i++) {
for (int j = 0; j <= bagSize; j++) {
System.out.print(dp[i][j] + "\t");
}
System.out.println();
}
}
基础二
一维数组遍历
public static void bag_d(int[] weight, int[] value, int bagSize) {
// dp[i] 代表背包重量为 i 时 所装物品的最大价值
int[] dp = new int[bagSize + 1];
// 遍历顺序:先遍历物品,再遍历背包容量
for (int i = 0; i < weight.length; i++) {
// 背包重量从后向前遍历
// 从后往前循环,每次取得状态不会和之前取得状态重合,这样每种物品就只取一次了
for (int j = bagSize; j >= weight[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
}
}
for (int j : dp) {
System.out.print(j + "\t");
}
}
416. 分割等和子集
public int integerBreak(int n) {
// dp[i] 代表整数 i 拆分后的最大乘积
int[] dp = new int[n + 1];
dp[2] = 1;
for (int i = 3; i <= n; i++) {
// j * (i- j) 代表把 i 拆分为 j 和 i - j 两个数相乘
// j * dp[i- j]代表把 i 拆分成 j 和继续把 (i - j) 这个数拆分,取(i - j)拆分结果中的最大乘积与j相乘
for (int j = 1; j < i - 1; j++) {
dp[i] = Math.max(dp[i], Math.max(dp[i - j], i - j) * j);
}
}
return dp[n];
}
1049. 最后一块石头的重量 II
public int lastStoneWeightII(int[] stones) {
if (stones == null) {
return 0;
}
if (stones.length == 1) {
return stones[0];
}
int sum = 0;
for (int stone : stones) {
sum += stone;
}
int target = sum >> 1;
// dp[i] 容量为i的背包装的最大石头重量
int[] dp = new int[target + 1];
// 遍历物品
for (int stone : stones) {
// 遍历背包
for (int j = target; j >= stone; j--) {
// 重量是stones[i],价值是stones[i]
// 两种情况,要么放,要么不放
dp[j] = Math.max(dp[j], dp[j - stone] + stone);
}
}
return sum - 2 * dp[target];
}
2021.12.26 10:40

浙公网安备 33010602011771号