目录
背包问题
背包问题分为01背包问题、完全背包问题、多重背包问题、分组背包问题。
具体算法思想和思路见代码随想录或者看中国大学MOOC里面的这节内容
算法思路和思想学会后最重要还得是实战。实践是检验真理的唯一标准。
例题
这里就直接上截图了。比较方便
01背包:
第一题:
代码:
import java.util.Scanner;
public class dotcpp {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();//采够药材的时间
int M = sc.nextInt();//采购药材个数
//建立时间和价值数组
int[] Time = new int[M+1];//采草药所需要的时间
int[] Value = new int[M+1];//草药的价值
for (int i = 1; i < M+1; i++) {
Time[i] = sc.nextInt();
Value[i] = sc.nextInt();
}
//构建dp数组用来存放最优解,创建该数组要比正常的大一,因为下面的循环是从1开始的。
int[][] dp = new int[M + 1][T + 1];
for (int i = 1; i < M + 1; i++) {
for (int j = 0; j < T + 1; j++) {
if (Time[i] > j) {
dp[i][j] = dp[i - 1][j];
}else{
dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-Time[i]]+Value[i]);
}
}
}
System.out.println(dp[M][T]);
}
}
第二题:
代码:
import java.util.Scanner;
public class dotcpp {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int M = sc.nextInt();//背包最大容量
int N = sc.nextInt();//物品数量
//定义物品数量和价值数组
int[] Wi = new int[N + 1];//物品数量数组
int[] Ci = new int[N + 1];//物品价值数组
for (int i = 1; i < N + 1; i++) {
Wi[i] = sc.nextInt();
Ci[i] = sc.nextInt();
}
int[][] dp = new int[N + 1][M + 1];
for (int i = 1; i < N + 1; i++) {
for (int j = 0; j < M + 1; j++) {
if (Wi[i] > j) {
dp[i][j] = dp[i - 1][j];
}else{
dp[i][j]=Math.max(dp[i-1][j],dp[i-1][j-Wi[i]]+Ci[i]);
}
}
}
System.out.println(dp[N][M]);
}
}
上面是01背包问题最基础做法,也算是个模板做法,我知道二维dp数组可以优化成一维dp数组,这个看个人习惯,哪个顺手就用哪个不做强求。
完全背包:
代码:
import java.util.Scanner;
public class dotcpp {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int M = sc.nextInt();//背包容量
int N = sc.nextInt();//物品数量
int[] Wi = new int[N + 1];//重量数组
int[] Ci = new int[N + 1];//价值数组
for (int i = 1; i < N + 1; i++) {
Wi[i] = sc.nextInt();
Ci[i] = sc.nextInt();
}
int[][] dp = new int[N + 1][M + 1];
for (int i = 1; i < N + 1; i++) {
for (int j = 0; j < M + 1; j++) {
for (int k = 0; k * Wi[i] <= M; k++) {
if (k * Wi[i] > j) {
dp[i][j] = dp[i][j];
} else {
dp[i][j] = Math.max(dp[i][j], dp[i - 1][j - k * Wi[i]] + k * Ci[i]);
}
}
}
}
System.out.println("max="+dp[N][M]);
}
}
混合背包:
这个例题输出是错误的。正确应该是11.
代码:
混合背包这段代码,我输出只能通过70%,具体哪块有问题我也没看出来,如果有大佬能看出麻烦留言或私信给予我改正。
题目链接:混合背包
import java.util.Scanner;
public class dotcpp {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int M = sc.nextInt();//背包容量
int N = sc.nextInt();//物品数量
int[] Wi = new int[N + 1];
int[] Ci = new int[N + 1];
int[] Pi = new int[N + 1];
for (int i = 1; i < N + 1; i++) {
Wi[i] = sc.nextInt();//重量
Ci[i] = sc.nextInt();//价值
Pi[i] = sc.nextInt();//数量
}
int[][] dp = new int[N + 1][M + 1];
for (int i = 1; i < N + 1; i++) {
for (int j = 0; j < M + 1; j++) {
//01背包问题
if (Pi[i] == -1) {
if (Wi[i] > j) {
dp[i][j] = dp[i - 1][j];
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - Wi[i]] + Ci[i]);
}
}
//完全背包
else if (Pi[i] == 0) {
for (int k = 0; k * Wi[i] <= j; k++) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - k * Wi[i]] + k * Ci[i]);
}
}
//多重背包
else {
for (int h = 0; h * Wi[i] <= j && h <= Pi[i]; h++) {
dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - h * Wi[i]] + h * Ci[i]);
}
}
}
}
System.out.println(dp[N][M]);
}
}