背包问题c++实现_C#实现背包问题(动态规划)

本文介绍了背包问题的动态规划算法,特别是0-1背包问题。当背包容量为m,有i个物品时,如何通过动态规划找到使背包总价值最大化的物品组合。文章详细讲解了穷举法、递归求解(带与不带备忘录)以及动态规划自底向上的方法,并给出了相应的C++和C#实现。
摘要由CSDN通过智能技术生成

44fe8f6e66ac1fc32029e37bbc7d88ba.png

问题描述:

假设现有容量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,穷举法(把所有情况列出来,比较得到 总价值最大的情况)

如果容量增大,物品增多,这个方法的运行时间将成指数增长

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(Exhaustivity(10, w, p));
            Console.WriteLine(Exhaustivity(3, w, p));
            Console.WriteLine(Exhaustivity(4, w, p));
            Console.WriteLine(Exhaustivity(5, w, p));
            Console.WriteLine(Exhaustivity(7, w, p));
            
            Console.ReadKey();
        }

        public static int Exhaustivity(int m,int[] w,int[] p)
        {
            int i = w.Length-1;//物品的个数

            int maxPrice = 0;
            for (int j = 0; j < Math.Pow(2, m); j++)
            {
                //取得j 上某一个位的二进制值 
                int weightTotal = 0;
                int priceTotal = 0;
                for (int number = 1; number <= i; number++)
                {
                    int result = Get2(j, number);
                    if (result == 1)
                    {
                        weightTotal += w[number];
                        priceTotal += p[number];
                    }
                }
                if (weightTotal <= m &&priceTotal>maxPrice )
                {
                    maxPrice = priceTotal;
                }
            }
            return maxPrice;
        }
        //取得j上第number位上的二进制值,是1还是0
        public static int Get2(int j,int number)
        {
            int A = j;
            int B = (int)Math.Pow(2, number - 1);
            int result = A & B;
            if (result == 0)
                return 0;
            return 1;
        }
    }
}

2, 递归求解

(1)递归求解-自顶向下(不带备忘录)

/****************************************************
	文件:Program.cs
	作者:黄山学院--Li Qingshan
	邮箱: 2781838262@qq.com
	日期:2020/06/15 12:28   	
	功能:
*****************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 背包问题_递归法
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] weightArr = { 0, 3, 4, 5 };
            int[] priceArr = { 0, 4, 5, 6 };

            Console.WriteLine(UpDown(10, 3, weightArr, priceArr));
            Console.WriteLine(UpDown(3, 3, weightArr, priceArr));
            Console.WriteLine(UpDown(4, 3, weightArr, priceArr));
            Console.WriteLine(UpDown(5, 3, weightArr, priceArr));
            Console.WriteLine(UpDown(7, 3, weightArr, priceArr));

            Console.ReadKey();
        }

        static int UpDown(int m, int count, int[] weightArr, int[] priceArr)
        {
            if (m == 0 || count == 0)
            {
                return 0;
            }

            if (weightArr[count] > m)
            {
                return UpDown(m, count - 1, weightArr, priceArr);
            }
            else
            {
                int maxPrice1 = priceArr[count] + UpDown(m - weightArr[count], count - 1, weightArr, priceArr);
                int maxPrice2 = UpDown(m, count - 1, weightArr, priceArr);

                if (maxPrice1 > maxPrice2)
                {
                    return maxPrice1;
                }
                return maxPrice2;
            }
        }
    }
}

(2)递归求解-自顶向下(带备忘录)

/****************************************************
	文件:Program.cs
	作者:黄山学院--Li Qingshan
	邮箱: 2781838262@qq.com
	日期:2020/06/16 12:30   	
	功能:
*****************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 背包问题_动态规划_自顶向下_
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] weightArr = { 0, 3, 4, 5 };
            int[] priceArr = { 0, 4, 5, 6 };
            int[,] memo = new int[100, 100];

            Console.WriteLine(UpDown(10, 3, weightArr, priceArr, memo));
            Console.WriteLine(UpDown(3, 3, weightArr, priceArr, memo));
            Console.WriteLine(UpDown(4, 3, weightArr, priceArr, memo));
            Console.WriteLine(UpDown(5, 3, weightArr, priceArr, memo));
            Console.WriteLine(UpDown(7, 3, weightArr, priceArr, memo));

            Console.ReadKey();
        }

        static int UpDown(int m, int count, int[] weightArr, int[] priceArr, int[,] memo)
        {
            if (m == 0 || count == 0)
            {
                return 0;
            }

            if (memo[m, count] != 0)
            {
                return memo[m, count];
            }

            if (weightArr[count] > m)
            {
                return UpDown(m, count - 1, weightArr, priceArr, memo);
            }
            else
            {
                int temp;
                int maxPrice1 = priceArr[count] + UpDown(m - weightArr[count], count - 1, weightArr, priceArr, memo);
                int maxPrice2 = UpDown(m, count - 1, weightArr, priceArr, memo);

                if (maxPrice1 > maxPrice2)
                {
                    temp = maxPrice1;
                }
                else
                {
                    temp = maxPrice2;
                }
                memo[m, count] = temp;
                return temp;
            }
        }
    }
}

3,动态规划算法

我们要求得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)

(3)动态规划-自底向上

/****************************************************
	文件:Program.cs
	作者:黄山学院--Li Qingshan
	邮箱: 2781838262@qq.com
	日期:2020/06/16 12:33   	
	功能:
*****************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 背包问题_动态规划_自下向上_
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] weightArr = { 0, 3, 4, 5 };
            int[] priceArr = { 0, 4, 5, 6 };

            Console.WriteLine(UpDown(10, 3, weightArr, priceArr));
            Console.WriteLine(UpDown(3, 3, weightArr, priceArr));
            Console.WriteLine(UpDown(4, 3, weightArr, priceArr));
            Console.WriteLine(UpDown(5, 3, weightArr, priceArr));
            Console.WriteLine(UpDown(7, 3, weightArr, priceArr));

            Console.ReadKey();
        }

        static int[,] result = new int[11, 4];

        static int UpDown(int m, int count, int[] weightArr, int[] priceArr)
        {
            if (result[m, count] != 0) return result[m, count];
            for (int i = 1; i <= m; i++)
            {
                for (int j = 1; j <= count; j++)
                {
                    if (result[i, j] != 0) continue;

                    if (weightArr[j] > i)
                    {
                        result[i, j] = result[i, j - 1];
                    }
                    else
                    {
                        int maxPrice1 = priceArr[j] + result[i - weightArr[j], j - 1];
                        int maxPrice2 = result[i, j - 1];

                        if (maxPrice1 > maxPrice2)
                        {
                            result[i, j] = maxPrice1;
                        }
                        else
                        {
                            result[i, j] = maxPrice2;
                        }
                    }
                }
            }
            return result[m, count];
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值