01背包问题 动态规划 java(详细注释)

public class Knapsack {

    // 0/1背包算法,填表x,f,找最大价值
    public static void knapSack(int c, int n, int x[], int w[], int v[], int f[][]){
        // 填表f[][],第0行,第0列为0 ,即f[i][0] = f[0][j] = 0
        for (int i=0; i<=n; i++)
            f[i][0] = 0;
        for (int j=0; j<=c; j++)
            f[0][j] = 0;
        // 填表f[][],其他位置 f[i][j] = 核心公式
        // 表f 的意义是记录 背包容量从0到c 时的每个容量时的背包能有的最大价值
        for (int i=1; i<=n; i++) {    // 依次计算第i行,第0行已经填完,从 1 开始
            for (int j=1; j<=c; j++){ // 依次计算第i行每个元素,第0列已经填完,从 1 开始
                if (w[i] > j)// 如果 第i个物品的重量>背包当前容量 ,即第i个物品不可装
                    f[i][j] = f[i-1][j];    // 最大价值量不变
                else         // 如果 第i个物品可装入,比较一下是装入价值大,还是不装入价值大
                    f[i][j] = Math.max(f[i-1][j], v[i] + f[i-1][j-w[i]]);
/* 此处,我原来有个错误认识,可以装,可以不装,那肯定装了价值大啊,
   原来的理解错在哪,原来的理解是基于装进背包的物品就不再拿出来了,那肯定是越装越多,但是
   v[i] + f[i-1][j-w[i]] 的意思是 当前此物品的价值+(当前背包容量-此物品重量)时的最大物品价值
   (此种情况下可能会造成原来装入的物品已经被拿出来了)
   这个核心公式正是表达了 最优子结构性质:一个问题的最优解 包含了 子问题的最优解
*/
            }
        }
        // 打印 f 表的值
        System.out.println("表 f 的值:");
        for (int i=0; i<=n; i++){
            for (int j=0; j<=c; j++)
                System.out.printf("%-4d" , f[i][j]);
            System.out.println();
        }

        // 填表 x[i],计算总价值
        int j = c;
        for (int i=n; i>0; i--) {
            if (f[i][j] > f[i-1][j]) {    // 如果 第i个物品装入
                x[i] = 1;    // x[i] 置1
                j -= w[i];   // 背包重量减去 w[i]
            }
            else    // 如果 第i个物品不装入
                x[i] = 0;    // x[i] 置0,背包重量不变
        }
        // 打印 x 表的值 和 总价值
        System.out.println("表 x 的值:");
        for (int i=1; i<=n; i++)
            System.out.print("x" + i + " = " + x[i] + "\t");
        System.out.println();
        System.out.printf("总价值为: %d", f[n][c]);
    }

    public static void main(String[] args) {

        int c = 10;     // 背包总重量为 10
        int n = 5;      // 总的物品数为 5
        int x[] = new int[n+1]; // 是否装入 xi,即 xi = 1/0  (x[0]]位置不用)
        int w[] = new int[]{0,2,2,6,5,4};// xi 的重量 (w[0]位置不用)
        int v[] = new int[]{0,6,3,5,4,6};// xi 的价值 (v[0]位置不用)
        int f[][] = new int[n+1][c+1];   // f[i][j] 前i个物品装入容量为j的包 所得到的最大价值

        knapSack(c, n, x, w, v, f); // 调用0/1背包算法,填表x,f,找最大价值

    }
}

01背包问题 动态规划 java(详细注释)_第1张图片

你可能感兴趣的:(算法设计分析思考笔记)