java运用动态规划方法求解0-1背包问题实验
01背包问题动态规划
实验目的:
1) 掌握动态规划法的设计思想;
2)掌握动态规划法解题步骤;
3)学习运用动态规划法分析并解决0-1背包问题。
实验要求:
运用动态规划法分析并解决下表给定的0-1背包问题,5个物品重量分别是3,5,7,8,9和价值分别是4,6,7,9,10,求背包总价值最大问题
1 2 3 4 5
W 3 5 7 8 9
v 4 6 7 9 10
实验内容:
java语言实现用动态规划算法解决0-1背包问题,分析时间复杂性,体会动态规划算法解决问题的基本思路和步骤
0-1 背包问题具有最优子结构性质,可以据此定义递归关系,建立递归方程,并以自底向上的方式计算最优值,根据计算最优值时的得到的信息,构造最优解。
实验步骤:
package sf;
import java.util.Arrays;
import java.util.Scanner;
//实验四,动态规划,0/1背包
public class knap {
public static void Knap(int v[], int w[], int c, int n, int m[][]) {
/* v是价值向量,w是质量向量,c是背包容量,n物品数量,m是最价值矩阵*/
int jMax = Math.min(w[n] - 1, c);
/*从递归关系的公式中,我们可以看到最后一层递归是可选物品为n,此时的子问题中,背包容量有两种可能:
容量小于物品n的质量,容量大于或等于物品n的质量,这与递归关系中的两种情况相同。
此处w[n]-1表示的就是小于n的质量,选择w[n]-1和c中小的那个,就是先给容量小于w[n]的情况赋值*/
//对二维数组初始化
for (int j = 0; j <= jMax; j++) // jMax小于w[n],所以此处对m[n][j]赋值0
m[n][j] = 0;
for (int j = w[n]; j <= c; j++) // 此处j从w[n]开始增长,
m[n][j] = v[n]; //表示的情况是子问题中背包容量足够装下物品n,将n放入背包
for (int i = n - 1; i > 1; i--) {
/*可选物品为n的情况已经确定了,就已经具备了逐层求解的条件。求解从可选物品为n-1,n开始。*/
jMax = Math.min(w[i] - 1, c); // 先确定 0<= j <w[i]时的m[i][j]
for (int j = 0; j <= jMax; j++)
m[i][j] = m[i + 1][j];
for (int j = w[i]; j <= c; j++) // 确定j>=w[i]时的m[i][j]
m[i][j] = Math.max(m[i + 1][j], m[i + 1][j - w[i]] + v[i]);
}
m[1][c] = m[2][c]; //w[1]>c时的m[1][j]
if (c >= w[1]) //c>=w[1]时的m[1][j]
m[1][c] = Math.max(m[1][c], m[2][c - w[1]] + v[1]);
}
static void Traceback(int m[][], int w[], int c, int n, int x[]) {
for (int i = 1; i < n; ++i) {
if (m[i][c] == m[i + 1][c])
x[i] = 0;
else {
x[i] = 1;
c -= w[i];
}
}
//m[n][c]不为0,x[n]赋值1,为0,赋值0
if(m[n][c]>1) {
x[n] =1;
}
if(m[n][c]==0) {
x[n] =0;
}
}
public static void main(String[] args) {
int []w=new int[101];
int []v=new int[101];
int []x=new int[6];
int [][]m=new int[101][101];
Scanner sc=new Scanner(System.in);
System.out.println("输入背包容量:");
int c=sc.nextInt();
System.out.println("输入物品数量:");
w[0]=sc.nextInt();
v[0]=w[0];
System.out.println("输入各物质量:");
for (int i = 1; i <= w[0]; ++i) {
w[i]=sc.nextInt();
}
System.out.println("输入各物品价值:");
for (int i = 1; i <= w[0]; ++i) {
v[i]=sc.nextInt();
}
Knap(v, w, c, w[0], m);
Traceback(m, w, c, w[0], x);
//System.out.println(Arrays.toString(x));
System.out.println("选中的物品为1,未选中的为0:");
for (int i = 1; i <= w[0]; ++i) {
System.out.print(x[i]+" ");
}
System.out.println();
System.out.println("总价值为:");
System.out.println(m[1][c]);
}}