今天要尽量把前段时间写的算法都总结一遍。。不过分析写太慢了。。所以大部分找天再补上(≡(▔﹏▔)≡以后我还记得是怎么一回事么。。。),以后再补上算法分析的时候顺便可以再重新把算法看一遍~~~
0-1背包问题,因为都能搜到题目是啥米意思,所以就大概说一下输入输出
输入如下:第一行为背包总数n,背包最大容量C,第二行为对应各背包的载重量,第三行为对应各背包的价值量。
3 6
4 3 2
5.0 4.0 1.0
输出:6.0
package com.java.struture; import java.util.Scanner; public class ZeroOne { public static double bag(int n ,int C , int[]w, double[]v){ double [] Val = new double[2*n+1]; //i为当前对应的背包 for(int i = 0 ; i < n ;i++){ //j为剩余背包容量 for(int j = C; j >=0;j--){ if(j>=w[i] && Val[j] < Val[j-w[i]]+v[i]) Val[j] = Val[j-w[i]]+v[i]; } } return Val[C]; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); int nums = sc.nextInt();//背包总数 int C = sc.nextInt();//背包总容量 int [] w = new int[nums];//每个背包的重量 double [] v = new double[nums];//每个背包的价值 for(int i = 0 ; i < nums ;i++){ w[i] = sc.nextInt(); } for(int i = 0 ; i < nums ;i++){ v[i] = sc.nextDouble(); } double maxval = bag(nums,C,w,v); System.out.println(maxval); } }
如果剩余容量j>当前背包的容量w[i]这时候就考虑要不要把这个物品放上去了。
如果放进去后的价值量大于未放进去的价值量,那么就把它放进去,否则放弃。
上一句话是什么意思呢?我一开始在想的时候是带有疑问的,如果顺着放东西的思路来想的话,我现在背包剩余容量是6,我有一个重量是5的物品,这物品肯定是带有价值的,那放进去肯定会使得这个背包的价值量增大才对的,为什么还要通过判断决定是否放进去呢?
往反方向思考,这个背包容量是6,额,直接放图比较方便分析:
其实就是放入一个物品w[i],那么背包的价值就是由这个物品的价值v[i]和剩下容量的价值Val[j-w[i]]组成的。而看图可以简单看出我们需要的就是从这个3个Val[6]中寻找最大的Val[6]返回(Val[6]表示剩余容量为6的背包的总价值量)。可以分析为放入物品1的话,价值量就由Val[2]+v[0]确定,而再一次循环的时候如果发现另外一个Val[6](放入另一个物品)比这个Val[6]大的话就替换这个Val[6],同理对所有剩余容量的背包都按这样的算法思路。如放入第一个物品后就寻找Val[2]最大的价值量,这样来使得Val[6]的价值量最大。