回溯法解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
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞