01背包问题 C#解法

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];
        }
    }
}

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

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值