一、01背包
- 给定一批物品的重量及价值,给定一个背包,在物品不超过背包的重量的情况下,找出最大价值,注意,物品都是单个的
代码实现
1、使用二维数组state[i][j]表示前i个物品重量为j的最大价值
package OneDaySuanFa;
/*
01背包问题:
给定一批物品的重量及价值,给定一个背包,在物品不超过背包的重量的情况下,找出最大价值
注意:物品都是单个的
*/
public class backage01 {
public static int backage01(int[] weight,int[] value,int n,int w){
//weight数组表示物品重量;value数组表示物品价值;n表示物品个数;w表示背包重量
int[][] state = new int[n][w+1]; //state[i][j]表示前i个物品装满总重量为j的背包的最大价值
state[0][0] = 0;
if (weight[0] <= w){
state[0][weight[0]] = value[0];
}
for (int i = 1; i < n; i++){
for (int j = 0; j <= w; j++) {
if (weight[i] <= j){ //能放入的情况下
//可以选择放入或者不放入,找出最大价值
state[i][j] = Math.max(state[i-1][j-weight[i]] + value[i],state[i-1][j]);
}else {
//不能放入的情况下
state[i][j] = state[i-1][j];
}
}
}
int maxvalue = 0;
for (int i = 0; i <= w; i++){
if (state[n-1][i] > maxvalue){
maxvalue = state[n-1][i];
}
}
return maxvalue;
}
public static void main(String[] args) {
int[] weight = new int[]{1,2,3,4};
int[] value = new int[]{2,4,4,2};
System.out.println(backage01(weight,value,4,5));
}
}
2、使用一维数组
//切换成一维数组
public static int backage02(int[] weight,int[] value,int n,int w){
int[] dp = new int[w+1]; //dp[i]表示装满重量为i的背包的最大价值
dp[0] = 0;
if (weight[0] <= w){
dp[weight[0]] = value[0];
}
for (int i = 1; i < n; i++){
//二维转为一维时,需要逆序遍历
for (int j = w; j >= 0; j--){
if (j >= weight[i]){
dp[j] = Math.max(dp[j-weight[i]] + value[i],dp[j]);
}else{
dp[j] = dp[j];
}
}
}
int maxvalue = 0;
for (int i = 0; i <= w; i++){
if (dp[i] > maxvalue){
maxvalue = dp[i];
}
}
return maxvalue;
}
二、完全背包
- 给定一批物品的重量及价值,给定一个背包,在物品不超过背包的重量的情况下,找出最大价值
注意:每个物品都有无限个
代码实现
package OneDaySuanFa;
import java.util.Scanner;
public class backageComplete {
public static int backagecomplete(int[] weight,int[] value,int n,int w){
//weight数组表示物品重量;value数组表示物品价值;n表示物品个数;w表示背包重量
int[][] state = new int[n][w+1]; //state[i][j]表示前i个物品凑够总重量为j的最大价值
for (int i = 0; i <= w / weight[0]; i++){
state[0][i * weight[0]] = i * value[0];
}
for (int i = 1; i < n; i++){
for (int j = 0; j <= w; j++){
for (int k = 0; k <= w / weight[i]; k++){
//这里k表示物品的个数,每个物品都可以放多个
if (k * weight[i] <= j){ //放的下的情况,可以选择放或者不放
state[i][j] = Math.max(state[i-1][j - k * weight[i]] + k * value[i],state[i][j]);
//为什么不放会是state[i][j],不是state[i-1][j],因为物品可以放多个,不放可能是已经放了一个的情况
}else {
//放不下的情况
state[i][j] = state[i][j];
}
}
}
}
return state[n-1][w];
}
}
使用一维数组
public static int backagecomplete2(int[] weight,int[] value,int n,int w){
int[] dp = new int[w+1]; //dp[i]表示重量为i的最大价值
dp[0] = 0;
for (int i = 0; i < n; i++){
for (int j = weight[i]; j <= w; j++){
dp[j] = Math.max(dp[j-weight[i]] + value[i],dp[j]);
}
}
return dp[w];
}