java运用动态规划方法求解0-1背包问题实验

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]);

}}





请添加图片描述

  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值