01背包问题 C#解法

it2022-05-05  165

01背包问题

假设现有容量m的背包,有i个物品,重量分别为w[1],w[2]…w[i],价值分别为p[1],p[2]…p[i],将哪些物品放入背包可以使得背包的总价值最大?最大价值是多少? (示例1:m=10,i=3,物品重量-价值:3-4 , 4-5 , 5-6)

第一种 不带备忘的自顶向下法

using System; namespace CSharp { 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));//容量10,物品3 Console.ReadKey(); } public static int UpDown(int m, int i, int[] w, int[] p) { 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; } } } }

思路:对于最大价值,有四种情况: 1.当i或m为0时,此时背包容量为0或者物品个数为0,直接返回0。 2.当最后一个物品的重量超出容量,舍弃不用。返回i-1时的情况。 3.当最后一个物品的重量小于容量,可以装下但不放入时(小于最大价值),直接返回i-1时的情况。 4.当最后一个物品的重量小于容量,可以装下且放入时,记录此时价值并和之前作比较,返回较大的那一个。

递归解法,时空复杂度极高,效率低下。

第二种 动态规划

using System; namespace CSharp { class Program { static int[,] result = new int[11, 4]; static void Main(string[] args) { int[] w = { 0, 3, 4, 5 };//物品重量 int[] p = { 0, 4, 5, 6 };//物品价值 Console.WriteLine(BottomUp(10, 3, w, p));//容量10,物品3 Console.ReadKey(); } public static int BottomUp(int m, int i, int[] w, int[] p) { if (result[m, i] != 0) return result[m, i]; for (int M = 1; M < 11; M++) { for (int I = 1; I < 4; I++) { if (result[M, I] != 0) continue; if (w[I] > M) result[M, I] = result[M, I - 1]; else { int maxValue1 = result[M - w[I], I - 1] + p[I]; int maxValue2 = result[M, I - 1]; if (maxValue1 > maxValue2) result[M, I] = maxValue1; else result[M, I] = maxValue2; } } } return result[m, i]; } } }

思路:和前一个思路大致相同,唯一不同的是用一个数组来承接每次放入物品的价值,之后再次调用则不需要重新计算,直接取数组中的值即可。


最新回复(0)