回溯法解0-1背包问题

回溯法:

Knapsack.java

public class Knapsack {
	private double c;         //背包重量
	private int n;            //物品数量
	private double[] w;       //物品重量
	private double[] v;       //物品价值
	private int[] num;        //物品序号
	private double cw;        //当前背包重量
	private double cv;        //当前背包价值
	private double maxv;      //当前最优值
	private int[] bestx;      //当前最优解
	private int[] x;          //部分解
	
	public Knapsack(double[] weight, double[] value, double c){
		this.c =c;
		this.n = weight.length;
		
		w = new double[n];
		v = new double[n];
		
		num = new int[n];
		for(int i = 0; i < n; i++) {
			num[i] = i + 1;
			w[i] = weight[i];
			v[i] = value[i];
		}
		
		//将各物品按单位重量价值从大到小排序(排序)
		double tmp;
		int tmpp;
		for(int i = 0; i < n; i++) {
			for(int j = 1; j < n; j++) {
				if((v[j] / w[j]) > (v[j-1] / w[j-1])) {
					tmp = v[j-1];
					v[j-1] = v[j];
					v[j] = tmp;
					
					tmp = w[j-1];
					w[j-1] = w[j];
					w[j] = tmp;
					
					tmpp = num[j-1];
					num[j-1] = num[j];
					num[j] = tmpp;
				}
			}
		}
	}
	
	void cacu() {
		cw = 0;
		cv = 0;
		maxv = 0;
		bestx = new int[n];
		x = new int[n];
		
		backtrack(0);
		
		System.out.print("装入背包的总价值:");
		System.out.println(maxv);
		System.out.print("装入背包的物品序号:");
		for(int i=0; i < n; i++) {
			if(bestx[i] == 1) {
				System.out.print(num[i] + " ");
			}
		}
	}
	
	void backtrack(int t) {
		if(t >= n) {
			output(x);
			return;
		}
		
		for(int i=1; i>=0; i--) {
			x[t] = i;
			if(i == 1) {
				cw += w[t];
				cv += v[t];
				if(constraint(t)&&bound(t)) {
					backtrack(t+1);
				}
				cw -= w[t];
				cv -= v[t];
			}
			if(i == 0) {
				if(constraint(t)&&bound(t)) {
					backtrack(t+1);
				}
			}
		}
	}
	
	void output(int[] x) {
		for(int i = 0; i < n; i++) {
			bestx[i] = x[i];
		}
		maxv = cv;
	}
	
	boolean constraint(int t) {
		if(c < cw)  return false;
		return true;
	}
	
	boolean bound(int t) {
		double cwr = cw;
		double cvr =cv;
		while(t < n-1 && (w[t+1] <= (c-cwr))) {
			cwr += w[t+1];
			cvr += v[t+1];
			t++;
		}
		
		if(cvr <= maxv)  return false;
		return true;
	}
}

Test.java

import java.util.Scanner;

public class Test {
	public static void main(String[] args) {
		double c = 50;
		int n = 0;
		
		Scanner sc = new Scanner(System.in);
		System.out.print("输入背包容量:");
		c = sc.nextDouble();
		System.out.print("输入物品数量:");
		n = sc.nextInt();
		
		double[] w = new double[n];
		double[] v = new double[n];
		
		for(int i=1; i<=n; i++){
			System.out.print("输入物品" + i + "质量和价值:");
			w[i-1] = sc.nextDouble();
			v[i-1] = sc.nextDouble();
		}

		Knapsack x = new Knapsack(w, v, c);
		long start = System.nanoTime();
		x.cacu();
		long end = System.nanoTime();
		System.out.println();
		System.out.println("花费时间: " + String.valueOf(end - start) + "纳秒");
	}
}

    原文作者:回溯法
    原文地址: https://blog.csdn.net/siderealian/article/details/78776026
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞