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

问题描述:给定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 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值