背包问题和图论

01背包

给定N个物品和容量为C的背包,每个物品的体积为w[i],每个物品的价值为v[i],问如何装入物品使背包中的总价值最大?

思路:

给定一个F[i][j]二维数组,代表前i个物品装入容量为j的背包中的价值最大。

主要考虑第i件物品背包是否可以装的下。如果装的下,应该考虑装下的价值和不装的价值哪个大,则F[i][j] =max{ F[i - 1][j - w[i]] + v[i],F[i - 1][j] };如果装不下,则F[i][j] = F[i - 1][j] ;

建立的数组为F[i][j],大小为(N+1,C+1),这是需要考虑到什么都不装的时候价值为0;

w[i],大小为(0,N - 1);v[i],大小为(0,N - 1);

import java.util.Scanner;

public class pack01 {

	private int N;
	private int C;
	private int[] w;  //体积
	private int[] v;  //价值
	private int[][] F; //总价值
	private boolean[][] flag; //指示哪些装入背包
	
	public void init() {

		Scanner sc = new Scanner(System.in);
		System.out.println("请输入物品数量:");
		N = sc.nextInt();
		System.out.println("请输入背包大小:");
		C = sc.nextInt();
		
		w = new int[N];
		v = new int[N];
		System.out.println("请输入各物品大小:");
		for (int i = 0; i < N; i++) {
			w[i] = sc.nextInt();
		}
		System.out.println("请输入各物品价值:");
		for (int i = 0; i < N; i++) {
			v[i] = sc.nextInt();
		}
		F = new int[N + 1][C + 1];
		flag = new boolean[N + 1][C + 1];
		for (int i = 0; i < F.length; i++) {
			F[i][0] = 0;
			flag[i][0] = false;
		}
		for (int i = 0; i < F[0].length; i++) {
			F[0][i] = 0;
			flag[0][i] = false;
		}
	}
	
	public void solution() {
		
		for(int i = 1; i <= N; i ++) {
			for (int j = 0; j <= C; j++) {
				if(j > w[i - 1]) {  //可以装的下
					if(F[i - 1][j - w[i - 1]] + v[i - 1] > F[i - 1][j]) {  //不添加装入背包的内容就用下面一句max()
						F[i][j] = F[i - 1][j - w[i - 1]] + v[i - 1];
						flag[i][j] = true;
						
					}else {
						F[i][j] = F[i - 1][j];
					}
					//F[i][j] = Math.max(F[i - 1][j - w[i - 1]] + v[i - 1], F[i - 1][j]);
				}else {
					F[i][j] = F[i - 1][j];
				}
			}
		}
		
		//输出结果
		for(int i = 0; i <= N; i ++) {
			for (int j = 0; j <= C; j++) {
				System.out.print(F[i][j] + " ");
			}
			System.out.println();
		}
	
		int i = flag.length - 1;
		int j = flag[0].length - 1;
		while(i > 0 && j > 0) {
			if(flag[i][j] == true) {
				System.out.print("第" + i + "个物品装入");
				j = j - w[i - 1];
			}
			i --;
		}
	}

	public static void main(String[] args) {
		pack01 instance = new pack01();
		instance.init();
		instance.solution();
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值