算法-动态规划-背包问题

应用场景:

一个已知容量为4的背包,有3种商品分别为A、B、C,不同的商品有不同的价格,且重量也不相等

商品重量价格
A11500
B43000
C3

2000

问题1:如何存放商品到背包中,使得背包中的商品价值最大。(商品不能重复)

动态规划算法在这个应用中可以理解为:先求出背包容量为1的最优解,在这个基础上去尝试求出背包容量为2的最优解,……一直求出背包容量为4的解。

接下来用一张表格来说明:

容量1234
尝试放入A1500(A)1500(A)1500(A)1500(A)
尝试放入B1500(A)1500(A)1500(A)3000(B)
尝试放入C1500(A)1500(A)2000(C)2000(C)+1500(A)
  1. 假设从A商品开始放入背包,得到容量为1的最优解为:【A】;再求容量为2时的最优解:【A】;由于不能存放相同的商品,容量为2、3、4时的解都为【A】
  2. 接下来在存放A的基础上存放商品B:容量为1、2、3时,都放不下B,所以就取之前的最优解【A】;当容量为4时,先放入B,发现容量已满,再与之前的最优解进行比较,得到【B】
  3. 接下来在存放C:容量为1、2时,放不下C,所以就取之前的最优解【A】;当容量为3时,先放入B,发现容量已满,与之前的最优解比较,得到【C】;容量为4时,放入C,剩余容量为1,所以加上剩余容量的最优解【A】,得到【C、A】与之前的最优解进行比较,得到【C、A】

总体来说是,计算当前解时,有剩余容量时加上剩余容量的最优解,得到当前解后,再比较之前算得的当前容量最优解,取最大的那个解

代码:

public class DynamicProgramming {

    public static void main(String[] args) {
        int bagWeight = 4;//背包可装的重量
        char[] name = {'A','B','C'};//物品名称,例:name[0],为物品A
        int[] weigth = {1,4,3};//物品重量,例weight[0],为物品A的重量
        int[] val = {1500,3000,2000};//物品的价值,例val[0],为物品A的价值

        //1、创建表,也就是二维数组
        int proNum = name.length;//物品数量
        int[][] vals = new int[proNum][bagWeight];//创建以物品数量为行,背包容量为列的二维数组
        String[][] proNames = new String[proNum][bagWeight];//记录存放的物品
        for(int i=0;i<vals.length;i++){//i表示name数组中索引为i的商品,i=0时物品为A
            for(int j=0;j<vals[i].length;j++){//j表示容量为j+1
                //vals[i][j] 表示有0~i种物品,在j+1的容量下存放最优解的价值
                int w = j+1;//当前容量
                String proName = "";
                if (w>=weigth[i]){//当可以放下该物品时
                    int residue = w-weigth[i];//剩余容量
                    int v;//重新计算的值(不一定是最优解)
                    if(residue>0){
                        //如果有剩余容量,再加上剩余容量的最优解
                        if (i==0){//i==0时,没有最优解
                            v = val[i];
                            proName = proName+name[i];
                        }else{
                            //vals[i-1][residue-1]为0~i-1种物品时的剩余容量的最优解
                            v = val[i]+vals[i-1][residue-1];
                            proName = proName+name[i]+proNames[i-1][residue-1];
                        }
                    }else{
                        //没有剩余容量
                        v = val[i];
                        proName = proName+name[i];
                    }
                    //与最优解进行比较,得出最大值
                    if(i==0){   //i==0时,没有最优解
                        vals[i][j] = v;
                        proNames[i][j] = proName;
                    }else{  //vals[i-1][j]为当前容量的最优解
                        if(v>vals[i-1][j]){
                            vals[i][j] = v;
                            proNames[i][j] = proName;
                        }else{
                            vals[i][j] = vals[i-1][j];
                            proNames[i][j] = proNames[i-1][j];
                        }
                    }
                }else{//放不下该物品时,取之前的当前容量最优解
                    if(i!=0){
                        vals[i][j]=vals[i-1][j];
                        proNames[i][j] = proNames[i-1][j];
                    }
                }
            }
        }
        printArr(vals);
        printArr(proNames);
    }
    public static void printArr(int[][] arr){
        for(int i = 0;i<arr.length;i++){
            for(int j=0;j<arr[i].length;j++){
                System.out.print(arr[i][j]+" ");
            }
            System.out.print('\n');
        }
    }
    public static void printArr(String[][] arr){
        for(int i = 0;i<arr.length;i++){
            for(int j=0;j<arr[i].length;j++){
                System.out.print(arr[i][j]+" ");
            }
            System.out.print('\n');
        }
    }
}
>>>

价值
1500 1500 1500 1500 
1500 1500 1500 3000 
1500 1500 2000 3500 

物品
A A A A 
A A A B 
A A C CA 

所以最优解为放【C、A】价值为3500

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值