动态规划-01背包系列题,选取动态规划中采用01背包模型解题思路的几个例题
1.01背包问题解题思路
2.01背包问题实现
3.01背包系列-最多任务工资
4.01背包系列-数列不相邻数字最大和
5.01背包系列-数列找到指定和子数列
1.01背包问题解题思路
从右到左进行解析,分析第n个物品的状态,第n个物品只有“放”和“不放“俩种状态,在“放”状态下,某些变量发生变化,以及放情况下,与前面子问题之间的联系。在“不放”状态下,即考虑前n-1个物品。
每个物品都有俩种状态,动态规划,相当于列出所有情况,从中挑选子问题的最优解。
所以首先要从后往前分析问题,给出状态转移方程,然后判定边界情况,然后从前往后实现代码,填充中间数组(一维数组,二维数组)。
2.01背包问题实现
题目:有一个包和n个物品,包的容量为m,每个物品都有各自的体积和价值。问当这n个物品放在包里而物品的体积总数不超过包的容量m时,如何让背包具有最大价值?
分析:
1.建模:使用数组分别存储这n个物品的体积和价值
v[n] = {v1,v2,v3,….vn};
w[n] = {w1,w2,w3,..wn};
2.确定子问题:n个物品加入容量为m的包里f(n,m),第n个物品有俩种选择,放或不放,如果放,包的剩余容量为m-vn,价值为wn + f(n-1,m-vn)
如果不放,包的剩余容量为m,价值为f(n-1,m)
3.状态转移方程:f(n,m) = max{wn+f(n-1,m-vn),f(n-1,m)}
4.边界情况:
- n == 0 retutn 0
- m ==0 return 0
- m < 0 return f(n-1,m)
5.动态规划二维数组(画图更直观)
dp[i][j] = max{dp[i-1][j-vi]+wi,dp[i-1][j]}
dp[i][j]表示前i件物品中,选择若干件放在容量为j的包里的最大价值1
6..代码实现
代码中给出递归法和动态规划法,用以比较
public class Bags {
public static void main(String[] args){
int[] weight = {
3,4,7,9,13};
int[] volume = {
2,4,3,5,7};
int m = 11;
int n = weight.length-1;
int res = getMaxValue(volume,weight,m,n);
System.out.println(res);
int res_dp = getMaxValue_DP(volume,weight,m);
System.out.println(res_dp);
}
/**
* 使用二维数组保存中间结果
* @param
* @param m
* @return
*/
private static int getMaxValue_DP(int[] volume, int[] weight, int m) {
if (volume.length == 0)
return 0;
if (m == 0)
return 0;
int[][] dp = new int[volume.length][m];
//填充第一列
for (int i = 0; i < dp.length; i++){
if (volume[i] <= 1){
dp[i][0] = dp[i][0] < weight[i] ? weight[i] : dp[i][0];
}
}
//填充第一行
for (int i = 0; i < m; i++){
if (volume[0] <= i+1){
dp[0][i] &#