寒假40多天,希望回去能够独当一面了,所以写下博客来记录自己的学习进度
问题描述:
假设现有容量m kg的背包,另外有i个物品,重量分别为w[1] w[2] ... w[i](kg),价值分别为p[1] p[2] ... p[i](元),将哪些物品放入背包可以使得背包的总价值最大?最大价值是多少?
(示例一:m=10 i=3 重量和价值分别为3kg-4元 4kg-5元 5kg-6元 )
1,穷举法(把所有情况列出来,比较得到 总价值最大的情况)
如果容量增大,物品增多,这个方法的运行时间将成指数增长
2,动态规划算法
我们要求得i个物体放入容量为m(kg)的背包的最大价值(记为c[i,m])。在选择物品的时候,对于每种物品i只有两种选择,即装入背包或不装入背包。某种物品不能装入多次(可以认为每种物品只有一个),因此该问题被称为0-1背包问题
对于c[i,m]有下面几种情况:
a、c[i,0]=c[0,m]=0
b、c[i,m]=c[i-1,m] w[i]>m(最后一个物品的重量大于容量,直接舍弃不用)
w[i]<=m的时候有两种情况,一种是放入i,一种是不放入i
不放入i c[i,m]=c[i-1,m]
放入i c[i,m]=c[i-1,m-w[i]]+p[i]
c[i,m]=max(不放入i,放入i)
这个递归算法是不带备忘的自顶向下法
思路如下:
设置m为背包重量
wp分别是物品的重量和价值的数组
自顶向下返回值m是可以存储的最大价值
如果物品个数i为0或者物品重量为0,返回0
如果物品重量大于背包承重,返回i-1的自顶向下的方法
之后从最重的物品开始递归求得最佳背包方案
int maxValue1 = UpDown(m - w[i], i - 1, w, p) + p[i];
上面这句求得放了这个w[i]物品之后价值为多少
int maxValue2 = UpDown(m, i - 1, w, p);
这句求得舍弃放了这个物品的背包的价值,递归调用,上面两句分别遍历所有方法
之后就是输出结果了
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace _01背包问题_递归实现_不带备忘的自顶向下法_ { class Program { static void Main(string[] args) { int m; int[] w = {0, 3, 4, 5}; int[] p = {0, 4, 5, 6}; Console.WriteLine(UpDown(10,3, w, p)); Console.WriteLine(UpDown(3, 3, w, p)); Console.WriteLine(UpDown(4, 3, w, p)); } //m是背包容量 //i是物品个数 //wp是物品的重量和价值的数组 public static int UpDown(int m,int i,int[] w,int[] p)//返回值是m可以存储的最大价值 { if (i == 0 || m == 0) return 0; if (w[i] > m) { return UpDown(m, i - 1, w, p); } else { int maxValue1 = UpDown(m - w[i], i - 1, w, p) + p[i]; int maxValue2 = UpDown(m, i - 1, w, p); if (maxValue1 > maxValue2) { return maxValue1; } return maxValue2; } } } }