最近在学习动态规划算法,网上资料很少有关于输出最优解详情的,于是给自己布置了一个小任务。纠结的时间蛮长的,但是加深了对算法的理解,比较开心。
背包问题简述:已知一个容量为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];
}
}
}
}
}