01背包问题 动态规划

01背包问题 动态规划

很有意思的问题。

写了点代码 C#实现

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;

namespace Package
{
    public class Item
    {
        public int weight;
        public int value;

        public Item(int w, int val) 
        {
            weight = w;
            value = val;
        }
    }

    public class Problem
    {
        //背包容量
        int content;
        int item_cnt;
        Item[] items;
        int[,] dps;

        public Problem()
        {
        }

        public void Init()
        {
            Console.Write("请输入背包容量(正整数):");
            string con = Console.ReadLine();
            while (!int.TryParse(con, out content) || content < 0) 
            {
                Console.Write("输入错误,请输入背包容量(正整数):");
                con = Console.ReadLine();
            }

            Console.Write("请输入物品数量(正整数):");
            con = Console.ReadLine();
            while (!int.TryParse(con, out item_cnt) || item_cnt < 0)
            {
                Console.Write("输入错误,请输入物品数量(正整数):");
                con = Console.ReadLine();
            }

            items = new Item[item_cnt];
            int temp_weight = 0, temp_val = 0;
            for (int idx  = 0; idx < items.Length; idx++) 
            {
                Console.Write("请输入物品{0}重量(正整数):", idx+1);
                con = Console.ReadLine();
                while (!int.TryParse(con, out temp_weight) || temp_weight < 0)
                {
                    Console.Write("输入错误,请输入物品{0}重量(正整数):", idx + 1);
                    con = Console.ReadLine();
                }

                Console.Write("请输入物品{0}价值(正整数):", idx + 1);
                con = Console.ReadLine();
                while (!int.TryParse(con, out temp_val) || temp_val < 0)
                {
                    Console.Write("输入错误,请输入物品{0}价值(正整数):", idx + 1);
                    con = Console.ReadLine();
                }

                items[idx] = new Item(temp_weight, temp_val);
            }
        }

        public void Display()
        {
            Console.WriteLine("========问题信息========");
            Console.WriteLine("背包容量:{0} 物品数量:{1}", content, item_cnt);
            for (int idx = 0; idx < items.Length; idx++) 
            {
                Console.WriteLine("物品{0} (重量:{1} 价值:{2})", idx+1, items[idx].weight, items[idx].value);
            }
        }

        public void Cal()
        {
            int h_cnt = item_cnt + 1;
            int l_cnt = content + 1;
            dps = new int[h_cnt, l_cnt];
            for (int item = 0;item < h_cnt; item++) 
            {
                for (int cidx = 0; cidx < l_cnt; cidx++) 
                {
                    if (item == 0) 
                    {
                        dps[item, cidx] = 0;
                    }
                    else
                    {
                        if (cidx < items[item - 1].weight)//背包在此容量下压根就装不上
                        {
                            dps[item, cidx] = dps[item - 1, cidx];
                        }
                       else//能装 装和不装取最大
                        {
                            dps[item, cidx] = Math.Max(dps[item-1, cidx], dps[item-1, cidx-items[item-1].weight] + items[item-1].value);
                        }
                    }
                }
            }
        }

        public void Answer()
        {
            Console.WriteLine("========dp table========");
            for (int h = 1; h < item_cnt + 1; h++)
            {
                for (int l = 0; l < content + 1; l++)
                {
                    Console.Write("{0}   ", dps[h, l]);
                }
                Console.WriteLine();
            }

            Console.WriteLine("最大价值:{0}", dps[item_cnt, content]);
            Console.Write("背包信息:");
            Plan(item_cnt, content);
            Console.WriteLine();
        }

        void Plan(int h, int l)
        {
            if (l <= 0 || h <= 0)
                return;

            if (dps[h - 1,l] != dps[h,l])
            {
                Plan(h-1, l - items[h-1].weight);
                Console.Write("物品{0} ", h);
            }
            else
            {
                Plan(h-1, l);
            }
        }
    }

    internal class Program
    {
        static bool IsContinue()
        {
            Console.WriteLine("是否继续(Y/N)?");
            string val = Console.ReadLine();
            while (val != "Y" && val != "y" && val != "N" && val != "n")
            {
                Console.WriteLine("是否继续(Y/N)?");
                val = Console.ReadLine();
            }

            if (val == "Y" || val == "y")
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        static void Main(string[] args)
        {
            Problem problem = new Problem();
            do
            {
                problem.Init();
                problem.Display();
                problem.Cal();
                problem.Answer();
            } while (IsContinue());
         }
    }
}

程序运行结果

在这里插入图片描述

代码和程序已经上传

代码和程序

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
01背包问题是一个经典的动态规划问题。它的目标是在给定背包容量的情况下,选择一些物品放入背包中,使得物品的总价值最大化,同时要保证背包的容量不超过限制。根据动态规划的原理,我们可以通过以下步骤来解决01背包问题: 1. 问题抽象化:将问题抽象为在给定背包容量和物品列表的情况下,选择一些物品放入背包中,使得物品的总价值最大化。 2. 建立模型:定义变量Vi表示第i个物品的价值,Wi表示第i个物品的体积。定义V(i,j)为当前背包容量j,前i个物品最佳组合对应的价值。 3. 寻找约束条件:约束条件是背包的容量不能超过限制,即对于每个物品i,有Wi <= j。 4. 判断是否满足最优性原理:最优性原理指的是最优解的子问题也是最优解。在01背包问题中,如果我们选择放入第i个物品,那么剩余背包容量就变为j-Wi,此时的最优解就是V(i-1,j-Wi)加上第i个物品的价值Vi。如果我们选择不放入第i个物品,那么最优解就是V(i-1,j)。因此,我们可以得到递推关系式:V(i,j) = max(V(i-1,j), V(i-1,j-Wi) + Vi)。 5. 找大问题与小问题的递推关系式:根据上述递推关系式,我们可以通过填表的方式来计算出所有的V(i,j)。 6. 填表:从i=1到n,j=0到背包容量的范围,依次计算V(i,j)的值。 7. 寻找解组成:通过填表的过程,我们可以得到最优解对应的V(n,C)的值,其中C为背包的容量。然后,我们可以根据V(i,j)的值逆推出最优解的组成方式。 综上所述,通过以上步骤,我们可以使用动态规划来解决01背包问题,并得到最优解以及解的组成。 #### 引用[.reference_title] - *1* *2* *3* [【动态规划01背包问题(通俗易懂,超基础讲解)](https://blog.csdn.net/qq_38410730/article/details/81667885)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

当当小螳螂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值