动态规划---0-1背包问题

来源:互联网 发布:360水滴破解软件 编辑:程序博客网 时间:2024/06/05 04:27

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

记m[i][j],前i件物品,放入背包容量为j的背包时问题的最优值。
递归式:
当j>=w[i]时:
m[i][j]=max{m[i-1][j], m[i-1][ j-w[i] ]+v[i]}
当j < w[i]时:
m[i][j] =m[i-1][j]

算法实现:

public class KnapsackProblem {    /*     * w[]:物品重量,下标从0开始,w[0]代表第1件物品重量     * v[]:物品价值,下标从0开始。     * c:背包容量     * m[i,j]:下标从1开始,前i件物品放入容量为j的背包可以获得的最大价值     */    public int[][] knapsack(int[] w,int[] v,int c,int n){        int i,j;        int[][] m= new int[n+1][c+1];        for(i=0;i<=n;i++)//初始化            m[i][0]=0;        for(j=0;j<=c;j++)            m[0][j]=0;        for(i=1;i<=n;i++)            for(j=1;j<=c;j++){                if(j<w[i-1])//背包容量没有第i件物品重量大,放不下                    m[i][j]=m[i-1][j];                else{                    if(m[i-1][j]>=m[i-1][j-w[i-1]]+v[i-1])                        m[i][j]=m[i-1][j];                    else                        m[i][j]=m[i-1][j-w[i-1]]+v[i-1];                }            }           return m;    }    // 逆推法求出最优解     public int[] traceBack(int[][] m,int[] w,int c,int n){        int[] x = new int[n];//x[i]表示第i-1件物品是否被选中        for(int i=n;i>0;i--)            if(m[i][c]>m[i-1][c]){                x[i-1]=1;//第i件物品被选中,记为1                c-=w[i-1];//剩余背包容量            }else                x[i-1]=0;        return x;    }    public static void main(String[] args) {        int n=5; //物品个数        int c=10;//背包容量        int[] w = new int[]{4,2,6,5,4};//每个物品重量        int[] v = new int[]{6,3,5,4,6};//每个物品价值        KnapsackProblem k = new KnapsackProblem();        int[][] m=k.knapsack(w, v, c, n);        System.out.println("最大值:"+m[n][c]);        int[] x = k.traceBack(m, w, c, n);        System.out.print("被选中的物品:");        for(int i=0;i<x.length;i++)            System.out.print(x[i]+" ");    }}
最大值:15被选中的物品:1 1 0 0 1 
0 0