实验一
分析
目标:在不超过背包容量的情况下,最多能获得多少价值
子问题状态:f[j]:表示前i件物品放入容量为j的背包得到的最大价值
状态转移方程:f[j] = max{f[j],f[j - weight[i]] + value[i]}
初始化:f数组全设置为0
输出顺序:顺序输出物品编号
注意:这里另外开辟数组G[i][v],标记上一个状态的位置
G[i][v] = 1:表示物品i放入背包了,上一状态为G[i - 1][v - weight[i]]
G[i][v] = 0:表示物品i没有放入背包,上一状态为G[i - 1][v]
代码
import java.util.Scanner;
public class one
{
public static int[][] knapSack(int[] w,int[] v,int N,int M){
int dp[][] = new int[N+1][M+1];
for (int i = 0; i < N; i++) {
dp[i][0]=0;
}
for (int i = 0; i < M; i++) {
dp[0][i]=0;
}
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
if(w[i]>j){
dp[i][j]=dp[i-1][j];
}else{
int value1 = dp[i-1][j-w[i]]+v[i];
int value2 = dp[i-1][j];
dp[i][j]=Math.max(value1,value2);
}
}
}
return dp;
}
// public static void PrintKnapsack_recursion(int i,int j,int dp[][],int v[],int w[]){
// for
// }
public static void main(String args[]) {
Scanner scanner = new Scanner(System.in);
int N=scanner.nextInt();
int M=scanner.nextInt();
int[] v=new int[N+1];
for (int i = 1; i <=N ; i++) {
v[i]=scanner.nextInt();
}
int[] w=new int[N+1];
for (int i = 1; i <=N ; i++) {
w[i]=scanner.nextInt();
}
int dp[][]=knapSack(w,v,N,M);
System.out.println( dp[N][M]);
int[] x = new int[N];
int p=0;
for (int i = N; i >0 ; i--) {
if(M-w[i]<0)continue;
if(dp[i][M]==dp[i-1][M-w[i]]+v[i]){
x[p++]=i;
M-=w[i];
}
}
for (int i = p-1; i >=0 ; i--) {
System.out.print(x[i]+" ");
}
}
}
测试用例
5 8
2 1 4 3 5
1 4 2 3 5
输出结果
11
1 3 5
代码截图
实验二
代码
import java.util.Scanner;
public class two {
public static void main(String[] args) {
int x[] = new int[1000];
int v[] = new int[1000];
int w[] = new int[1000];
int b[] = new int[1000];
int f[][][] = new int[100][100][100];
Scanner s = new Scanner(System.in);
int n, m, d;
n = s.nextInt();
m = s.nextInt();
d = s.nextInt();
for (int i = 1; i <= n; i++)
v[i] = s.nextInt();
for (int i = 1; i <= n; i++)
w[i] = s.nextInt();
for (int i = 1; i <= n; i++)
b[i] = s.nextInt();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
for (int k = 1; k <= d; k++) {
if (j < w[i] || k < b[i])
f[i][j][k] = f[i - 1][j][k];
else
f[i][j][k] = max(f[i - 1][j][k], f[i - 1][j - w[i]][k - b[i]] + v[i]);
}
System.out.println("总价值为:" + f[n][m][d]);
}
private static int max(int i, int j) {
if (i >= j)
return i;
else
return j;
}
}
测试用例
5 8 8
2 1 4 3 5
1 4 2 3 5
2 3 5 2 4
运行结果
实验总结
1、01背包问题是最基本的背包问题,它包含了背包问题中设计状态、方程的最基本思想,另外,别的类型的背包问题往往也可以转换成01背包问题求解。故一定要仔细体会上面基本思路的得出方法,状态转移方程的意义,以及最后怎样优化的空间复杂度。
2、解决动态规划的三个基本要素:
最优子结构
边界条件
状态转移方程