一、问题描述
二、求解
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace dpBagPro
{
class Program
{
/*
* 动态规划之0-1背包问题
* 现给出4个物品,编号,重量,价值如下:
* 编号 1 2 3 4
* 重量 2 3 4 5
* 价值 3 4 5 6
* 有个背包能容纳重量为8,求装入此四种物品的最大价值
*
* 分析,先将题目给的信息存入数组
* 重量w[5],来源于英语weight->重量,价值v[5],来源于英语value->价值,
* 复杂问题简单化,第一波先分析前一个物品装入一个容量1的背包价值多少,
* 装到容量为8的价值是多少,第二波分析前两个物品装入容量1价值多少,直到8
* 手动列出表格,行代表第几个物品,列是背包容量,行,列前面都要加0,
* 得到一个二维数组并手动填入自己计算的值(这是答案)
* 最大价值二维数组,这个二维数组命名dp[i][j],来源于动态规划英语-dynamic Programming
* dp第一个长度i是行数+1->物品数+1,第二个长度j是列数+1->背包容量+1,加的1是放0
* 本题i 取值范围为[1,4],j取值范围是[1,8],第一个表示for循环初始值1,第二个表示小于等于4/8
* dp[5][9]
* 列出表格得到答案倒推公式可得,为了防止出错带回去公式再算几个验证
* if(w[i]>j){ //w[i]表示第几号物品的重量,如w[1]=2,w[2]=3...
* 物品i直接装不下,去看前面的物品吧
* dp[i,j]=dp[i-1,j];
* }else{
* //装入物品i,物品i价值v[i]+上一个物品装剩余容量的背包最大价值
* A=v[i]+dp[i-1][j-w[i]];
* // 不装物品就返回看看上一个物品价值吧。
* B=dp[i-1][j]
*
* dp[i][j]=max(A,B)
* }
*
*
*/
public static int[,] dp = new int[5, 9];// 结果数组
public static int[] w = new int[5] { 0, 2, 3, 4, 5 };// 物品重量数组
public static int[] v = new int[5] { 0, 3, 4, 5, 6 };// 物品价值数组
public static void Main(string[] args)
{
for (int i = 1; i <= 4; i++)
{
for (int j = i; j <= 8; j++)
{
if (w[i] > j)
{ //w[i]表示第几号物品的重量,如w[1]=2,w[2]=3...
// 物品i直接装不下,去看前面的物品吧
dp[i, j] = dp[i - 1, j];
}
else
{
//装入物品i,物品i价值v[i]+上一个物品装剩余容量的背包最大价值
int A = v[i] + dp[i - 1, j - w[i]];
// 不装物品就返回看看上一个物品价值吧。
int B = dp[i - 1, j];
// 返回最大
dp[i, j] = max(A, B);
}
}
}
// 输出最后结果
Console.WriteLine(dp[4, 8]);
Console.ReadLine();
}
// 比大小
public static int max(int a, int b)
{
if (a > b)
{
return a;
}
else
{
return b;
}
}
}
}
三、总结
1.搞了我两天啊,好家伙,看懂就不容易了,我数学真不太好。前面三角函数就是线性代数,背包问题是数学归纳。
2.共性就是先将问题简单化,搞子问题,抽出公式,大佬们一看一分析就得到了,我不行。
看了几篇文章和b站视频,我比较接受好的办法是,先自己列出二维数组求解答案,这个人自己算真不难,难得是找出共性得到公式,得到就好搞了,得到公式为了以防万一再填写一遍表格验证对错,两相验证。