动态规划算法——背包问题 输出最优解和背包中的物体

最近在学习动态规划算法,网上资料很少有关于输出最优解详情的,于是给自己布置了一个小任务。纠结的时间蛮长的,但是加深了对算法的理解,比较开心。

背包问题简述:已知一个容量为m的背包,现在有一个不同重量不同价值的物品,问怎样在背包容量限制下达到利益最大化。

已知条件:                序号:      0  1  2 3  4 5  6 7  8   9  10 11 12 13

物品数组:  int[] w = { 0, 3, 4, 5 ,6,9,10,8,12,11,13,14,15,16};

物品价值数组           int[] p = { 0, 4, 5, 6 ,7,8,9,10,11,10,12,15,17,18};

问题分析:将大问题可以分解拆分成无数的小问题。假设背包容量为0~2时,物品往里放入,则没有任何东西能放得下

假设背包容量为3时,物品有两种状态:1、①号放入 2、①号不放入。求最优解记录result[3,1]

背包容量为4  物品有这几状态:1、②号放入,加上当前最优解,求背包去掉①号物品剩下的重量的最优解 剩余容量4-w[2]=0

      2、②号不放入。求①号放入的最优解 求result[4,1]

比较得出较大值。

………………………………………………

背包容量[m]

int res1 = result[tempI-w[tempJ], tempJ-1] + p[tempJ];//放入
int res2 = result[tempI,tempJ-1];//不放入
result[tempI, tempJ] = Math.Max(res1, res2);

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace 背包_自底向下_
{
    class Program
    {
        public static int[,] result;
        public static List<int> best;//存储最优解数组
        public static int TotalWeight;//最优解总重量
        static void Main(string[] args)
        {
            int m = 0;
            int.TryParse(Console.ReadLine(), out m);
            int[] w = { 0, 3, 4, 5 ,6,9,10,8,12,11,13,14,15,16};
            int[] p = { 0, 4, 5, 6 ,7,8,9,10,11,10,12,15,17,18};
            result = new int[m + 1, w.Length];
            best = new List<int>();
            Console.WriteLine("最优解总价值:" + BottomUp(m, w.Length - 1, w, p));
            getList(w.Length, m, w);
            Console.Write("总重量:"+TotalWeight);
            for (int i = 0; i < best.Count; i++) {
                Console.Write(" 重量:"+w[best[i]]+"价值:"+p[best[i]]);
            }
            Console.ReadKey();
        }

        /// <summary>
        /// 自底向下递归算法
        /// </summary>
        /// <param name="m">背包容量</param>
        /// <param name="w">物品重量</param>
        /// <param name="p">物品价值</param>
        /// <param name="i">物品个数</param>
        /// <returns></returns>
        public static int UpDown(int m,int i, int[] w, int[] p) {
            if (m == 0 || i == 0)
            {
                return 0;
            }
            if (result[m, i] != 0) {
                Console.WriteLine(i+" "+w[i]+" "+p[i]);
                return result[m, i];
            }
            if (w[i] > m)
            {
                result[m, i] = UpDown(m, i - 1, w, p);
                return result[m, i];
            }
            else {
                int maxValue1 = UpDown(m - w[i], i - 1, w, p) + p[i];//放入
                int maxValue2=UpDown(m, i - 1, w, p);//不放入
                result[m, i] = Math.Max(maxValue1, maxValue2);
                return result[m, i];
            }
        }
        public static int BottomUp(int m,int i,int[] w,int[] p) {
            if (result[m, i] != 0) {

                return result[m, i];
            }

            for (int tempI = 1; tempI <= m; tempI++) {
                for (int tempJ = 1; tempJ <= i; tempJ++)
                {
                    if (result[tempI, tempJ] != 0) continue;
                    if (w[tempJ] > tempI)
                    {
                        result[tempI, tempJ] = result[tempI, tempJ-1];
                    }
                    else {
                        int res1 = result[tempI-w[tempJ], tempJ-1] + p[tempJ];//放入
                        int res2 = result[tempI,tempJ-1];//不放入
                        result[tempI, tempJ] = Math.Max(res1, res2);
                    }
                }      
            }
           
            return result[m, i];
        }
        public static void getList(int length,int m,int[] w) {
            int tempM = m;
            for (int tempI = length-1; tempI >= 1; tempI--) {
                if (result[tempM, tempI] > result[tempM, tempI - 1]) {
                    best.Add(tempI);
                    TotalWeight += w[tempI];
                    tempM -= w[tempI];
                }
            }
        }
    }
}


猜你喜欢

转载自blog.csdn.net/lisa0626/article/details/79143571