0-1背包问题(java版)

来源:互联网 发布:数据库定时同步工具 编辑:程序博客网 时间:2024/06/05 19:38

问题描述:
给定n种物品和一背包。物品i的重量是wi,其价值为vi,背包的容量为C。问应如何选择装入背包的物品,使得装
入背包中物品的总价值最大?

对于一种物品,要么装入背包,要么不装。所以对于一种物品的装入状态可以取0和1.我们设物品i的装入状态为xi,xi∈ (0,1),此问题称为0-11背包问题。

`
public class PacketQuestion {
public static void main(String[] args) {
int c = 10;//背包的总容量
int[] w = {0,2,2,6,5,4};//每个物体的重量
int[] v = {0,6,3,5,4,6};//每个物理的价值

    int n = w.length;//计算物体的个数    int x[] = new int[n];//x[i]的值要么为0要么为1,1表示放当前i的物品,0表示不放当前i的物品    int[][] m = new int[n][11];//存放可能性的二维数组    packet0_1(m,w,v,c);//该方法就是构造最优解的那个二维数组m    //输出构造的二维数组的结果    for (int i = 1; i < m.length; i++) {        for (int j = 0; j < m[i].length; j++) {            System.out.print(m[i][j] + " ");        }        System.out.println();    }    /*     *输出结果为:     0 0 6 6 9 9 12 12 15 15 15      0 0 3 3 6 6 9  9  9  10 11      0 0 0 0 6 6 6  6  6  10 11      0 0 0 0 6 6 6  6  6  10 10      0 0 0 0 6 6 6  6  6  6  6      */    //根据构造的二维数组,给x赋值    answer(m,w,c,x);    System.out.print("是否装物品的数组:");    for (int i = 0; i < x.length; i++) {        System.out.print(x[i] + " ");    }    /*        结果为:是否装物品的数组(x数组的值为):0 1 1 0 0 1     */    //总价值    int value = getValues(v,x);    System.out.print("最高总价值 : ");    System.out.println(value);    /*     * 总价值 : 15     */}private static int getValues(int[] v, int[] x) {    int value = 0;//最初的价值为0    for (int i = 0; i < x.length; i++) {        value += v[i] * x[i];//当前物品的价值 * 该物体是否被放。    }    return value;}//根据最优解的结果为x数组赋值,顺序是从上到下,从左到右。x数组的值有两个,1表示选该物体,0表示不选该物体private static void answer(int[][] m,int[] w, int c, int[] x) {    int j = c;//最初的总重量    int i = 1;    int n = w.length;    //遍历每一行的值    for (i = 1; i < n-1; i++) {        //如果承重为j的包所放当前物体最大价值等于下一个物体的最大价值,说明该物体没有被放进包里,所以x[i] = 0        if (m[i][j] == m[i+1][j]) {            x[i] = 0;        }else{//反之,放入包里了,x[i]置1,包的空间数减去当前物体的重量            x[i] = 1;            j = j - w[i];//放该物体后,剩余的空间        }    }    x[n-1] = m[i][j] != 0 ? 1 : 0;   //承重为j的包所放当最后一个物体的价值不为0,说明放了最后一个物体,反之没有放。}private static void packet0_1(int[][] m, int[] w, int[] v, int c) {    int n = m.length;    //给二维数组的最后一行赋值    //因为最后一行只存放最后一个物体,所以背包承重大于物体重量,就放该物体,二维数组的就就是物体的价值,否则就不放该物体    for (int i = 0; i <= c; i++) {        //放该物体        if (i >= w[n-1]) {            m[n-1][i] = v[n-1];        }else{//不放该物体            m[n-1][i] = 0;        }    }    //从倒数第二行开始向前为每个二维数组对应的值赋值    for (int i = n - 2; i > 0; i--) {//控制行值        for (int j = 0; j <= c; j++) {//控制列值,也就是当前包的承重            if (j < w[i]) {                //如果当前背包的承重小于当前物体的重量,那么当前背包的承重就等于下一个位置的值                m[i][j] = m[i+1][j];            }else{                //否则就比较该位置放该物体,与不放该物体的价值哪个大,哪个大就放哪个                /*                 * m[i+1][j - w[i]] + v[i]:                 * v[i]是当前物体的价值                 * m[i+1][j - w[i]]是除去当前物体的重量后背包能放的最大重量,第j-w[i]的背包能放的最大价值就是i+1列                 * m[i+1][j]:表示不放该物体时背包能放的最大价值                 */                m[i][j] = Math.max(m[i+1][j - w[i]] + v[i], m[i+1][j]);            }        }    }}

}

`

0 0
原创粉丝点击