超详解动态规划之0-1背包问题,java语言实现

超详解动态规划之0-1背包问题

问题:

问题:有 N 件物品和一个容量为 V 的背包。第 i 件物品的费用是 w[i],价值是 p[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
举例:假设v=20,w={5,6,3,7,8},p={6,7,4,8,9},则最大价值为23
逆向构造最优解输出哪些物品放入了背包

输入

5
20
5 6 3 7 8
6 7 4 8 9

输出

23
1 4 5

算法设计:

有n个物品,每个物品的重量为w[i],价值为v[i],背包的容量为w.选若干个物品放入背包,在不超过容量的前提下使获得的价值最大.
(1)确定合适的数据结构
采用一维数组w[i],v[i]来记录第i个物品的重量和价值;二维数组c[i][j]表示前i件物品放入一个容量为j的背包可以获得的最大价值.
(2)初始化
初始化c[][]数组0行0列为0:c[0][j]=0,c[i][0]=0;其中i=0,1,2,3…,n,j=0,1,2,3…w.
(3)循环阶段
①按照递归式计算第一个物品的处理情况,得到c[1][j],j=1,2,…w.
②按照递归式计算第二个物品的处理情况,得到c[2]j],j=1,2,…w.
③以此类推,按照递归式计算第n个物品的处理情况,得到c[n][j],j=1,2,3…,w.
(4)构造最优解
c[n][w]就是不超过背包容量能放入物品的最大价值.如果还想知道具体放入了哪些物品,就需要根据c[][]数组逆向构造最优解.我们可以用个一维数组x[i]来存储解向量.
①首先i=n,j=w,如果c[i][j]>c[i-1][j],则说明第n个物品放入了背包,令x[n]=1,j-=w[n];如果c[i][j]≤c[i-1][j],则说明第n个物品没有放入背包,令x[n]=0.
②i–,继续查找答案.
③直到i=1处理完毕.
这时已经得到了解向量(x[1],x[2],…x[n]),可以直接输出该解向量,也可以仅把x[i]=1的物品序号i输出.

代码:

import java.util.Scanner;
public class text1 {
    public static void main(String args[]){
        int n;//物品个数
        int w;//背包的容量
        int i,j;
        Scanner sc=new Scanner(System.in);
        System.out.println("请输入物品的个数");
        n=sc.nextInt();
        int []V=new int[n+1];//价值数组
        System.out.println("请输入背包的容量");
        w=sc.nextInt();//重量数组
        int []W=new int[w+1];
        int []x=new int[n+1];//逆向构造最优解的时候表示,该物品有没有放入背包
        int [][]c=new int[n+1][w+1];//表示前i个物品放入容器为j的背包获得的最大价值
        System.out.println("请输入每个物品的重量");
        for ( i=1;i<=n;i++){
            W[i]=sc.nextInt();
        }
        System.out.println("请输入每个物品的价值");
        for ( i=1;i<=n;i++){
            V[i]=sc.nextInt();
        }
        for ( i = 0; i <=n ; i++) {
            c[i][0]=0;//初始化第0列为零
        }
        for ( j=0;j<=w;j++){
            c[0][j]=0;//初始化第0行为0;
        }
        for ( i=1;i<=n;i++) //计算c[i][j]
           for( j=1;j<=w;j++)
               if(j<W[i]) //当物品的重量大于背包的重量,则不放入此物品
                   c[i][j] = c[i - 1][j];
               else //否则比较此物品放与不放是否能使得背包内的价值最大
                   c[i][j]=Math.max(c[i-1][j],c[i-1][j-W[i]]+V[i]);
        System.out.println(c[n][w]);
        //逆向构造最优解
        j=w;
        for(i=n;i>0;i--){
            if(c[i][j]>c[i-1][j]){
                x[i]=1;
                j-=W[i];
            }
            else
                x[i]=0;
        }
        System.out.println("装入背包的物品为:");
        for(i=1;i<=n;i++){
            if(x[i]==1){
                System.out.print(i+" ");
            }
        }
        }
    }

运行结果:

在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值