动态规划之 0-1 背包问题

动态规划问题一直以来都是利用空间换取时间。

在这里插入图片描述

动态规划问题一直以来最经典的就是 0 1背包问题 ,再有点难度就是 完全背包问题 以及多重背包问题

0-1背包问题

题目描述:有一个容量为 V 的背包,和一些物品。这些物品分别有两个属性,体积 w 和价值 v,每种物品只有一个。要求用这个背包装下价值尽可能多的物品,求该最大价值,背包可以不被装满。

其实这问题刚接触是 我靠 一脸懵逼 这是考数学呀!!! 瞬间感觉干饭都不香了。
其实只需要考虑每个物品两种形式 在 背 包 和 没 在 背 包 在背包 和 没在背包

第一步 对于每一个物品,有两种结果:能装下或者不能装下。

第一,包的容量比物品体积小,装不下,这时的最大价值和前i-1个物品的最大价值是一样的。(就是说口袋太小了 放不进去 ,,但是物品价值 和口袋里的物品一样值钱)

第二,还有足够的容量装下该物品,但是装了不一定大于当前相同体积的最优价值,所以要进行比较。(就是说 口袋很大 还能放里面 ,,但是和已经有的物品比较 说不来值钱还是不值钱)

第二步 就是考虑边界条件(万一装把口袋撑破了 ,是不是啥都装不进去了)
dp[i][j]啥意思 这样定义 就是说 把i个物品 装进 背包容量为 j 的背包 达到最大RMB价值。
初始时: dp[0][j]=0 (0<=j<=V)
来翻译一下 就是说 开始 i为0 里面没有东西 是空口袋 但是 j 不变 因为 口袋本身容量就这样大,里面没有东西 自然就不值钱为0
第三步考虑变换过程 就是转移状态
第i个物品的体积为w,价值为v,则状态转移方程为
当 j<w 时 dp[i][j]= dp[i-1][j]; 翻译一下 就是说第i件东西装不下 ,而且最大价值不改变,也就是有i行 没i也行 价值没变,但是有i容量就过载了
当 j<=w dp[i][j]=max(dp [i-1][ j-l ist[i].w] + v, dp[i-1][j]);这段太长了
解释一下 就是说 dp[i][j] 的值 由装i前的一个决定 比如 已经装了3斤 现在要装5斤 那么装这5斤 得看3斤装后的状态 万一3斤装了没位置了 那就不用装5斤了 。
所与i的前一个 dp[i-1][j-list[i].w] 这里加入v就好比 能装下5 斤,后边理解为 比较原本最大价值 如果装了价值变小了 还不如不装,所以求最大值 看看那各价值最大

接下来下代码 也是最头疼的

最大值就这

int max(int a, int b)//取最大值函数
{
    return a > b ? a : b;
}

背包结构体 和dp

struct Thing
{
    int w;
    int v;
}list[101];

int dp[101][1001];

终极main函数

int main()
{
    int s, n;//背包容量和物品总数
    while (scanf("%d%d", &s, &n) != EOF)
    {
        for (int i = 1; i <= n; i++)
        {
            scanf("%d%d", &list[i].w, &list[i].v);//读入每个物品的体积和价值
        }
        dp[0][0] = 0;
        for (int i = 1; i <= s; i++) dp[0][i] = INF;//初始化二维数组
        for (int i = 1; i <= n; i++)//循环每个物品,执行状态转移方程
        {
            for (int j = s; j >= list[i].w; j--)
            {
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - list[i].w] + list[i].v);
            }
            for (int j = list[i].w - 1; j >= 0; j--)
            {
                dp[i][j] = dp[i - 1][j];
            }
        }
        printf("%d\n", dp[n][s]);
    }
    return 0;
}

这里注意个问题 我是倒写

 for (int j = s; j >= list[i].w; j--)
 
 for (int j = list[i].w - 1; j >= 0; j--)

why why why 举手回答
那是因为 要求恰好装满背包时,把dp[0][0]设为0,其余dp[0][i]设为负无穷即可,这样只有恰好达到dp[n][s]时,dp[n][s]才为正值,所以 我们直接就认为 背包能装满s 容量 进而判断 当容量大于 i 间物品是就装入进去 , 来来 给画画
在这里插入图片描述
下节说说 用滚动数组优化问题 二维变一维
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值