浅谈动态规划的背包问题即题解 P1507 【NASA的食物计划】

借着这次机会写一写对于背包我的一些理解,也希望大佬们及时更正

一、动态规划

动态规划是求解决策过程最优化的数学方法,是指一种过程,并不算

是一类算法

动态规划一般可分为线性动规,区域动规,树形动规,背包动规四类,

本题和本题解都是关于背包问题展开的

二、背包问题

背包问题又分01背包和完全背包,二者本质区别就是可以拿物体的次

数,在这里不做区分

01背包:
有N件物品和一个容量为V的背包。第i件物品的体积是c[i],价值是w[i]。

求解将哪些物品装入背包可使价值总和最大。

从这个题目中可以看出,01背包的特点就是:每种物品仅有一件,可以选择放或不放。

因为动态规划的核心就是要求出状态转移方程

方法一:

这里我们先给出状态转移方程 dp[i][j]=max(dp[i-1][j],dp[i-1][j-c[i]]+w[i])

i代表当前一共选择的物品总数量

j代表当前选择的物体总体积

dp[i-1][j]就代表我们之前i-1个物品全部选择

dp[i-1][j-c[i]]+w[i]就代表抛弃前面的不选,只选当前的这一个

而dp[i][j]就是存储当前物体的总价值

那dp[n][V]就是最终的答案,就是可以选择物体的最大重量

方法二:

看到前一个状态转移方程,大家是不是隐约有种说不上来多余的感觉?

那恭喜你,你的肝很发达

(是不是在想这跟肝有什么关系,其实我也不知道qwq(逃

那么我们还是先看状态转移方程:

dp[j]=max(dp[j],dp[j-c[i]]+w[i]

是不是爽了很多,因为[i-1]在两边都出现了,可以舍去

这就是01背包问题,是不是不算太难?那我们再来看题解

题解
第一次看题我有点小蒙,这怎么会有三个数???(黑人疑惑脸)

仔细想了想原来很简单,只是背包问题多了一个条件,多一重循环就好

(用方法一的就设4重循环,用方法二的就舍3重循环,但我不确定4

重会不会爆)

下面来看一看代码

#include<iostream>
using namespace std;
int mv,mm,n,v[401],m[401],k[401],dp[401][401];
int main()

没营养的前4行

注意:开数组一定要看好题目,要不然开大了爆零,开小了不过

{
    cin>>mv>>mm>>n;
    for(int i=1;i<=n;i++)  cin>>v[i]>>m[i]>>k[i];

没营养的5-7行

for(int i=1;i<=n;i++){
    for(int j=mv;j>=v[i];j--){
        for(int p=mm;p>=m[i];p--){
            dp[j][p]=max(dp[j][p],dp[j-v[i]][p-m[i]]+k[i]);
        }
    }
}

这才是核心代码,仔细看是不是和01背包差不多呢

cout<<dp[mv][mm]; return 0; }
又是没营养的15-17行

这是我们最爱的完整代码

#include<iostream>
using namespace std;
int mv,mm,n,v[401],m[401],k[401],dp[401][401];
int main()
{
    cin>>mv>>mm>>n;
    for(int i=1;i<=n;i++)  cin>>v[i]>>m[i]>>k[i];
    for(int i=1;i<=n;i++){
        for(int j=mv;j>=v[i];j--){
            for(int p=mm;p>=m[i];p--){
                dp[j][p]=max(dp[j][p],dp[j-v[i]][p-m[i]]+k[i]);
            }
        }
    }
    cout<<dp[mv][mm];
    return 0;
}

友情链接:
dd大神的背包九讲 https://www.cnblogs.com/jbelial/articles/2116074.html

动态规划部分来自百度 https://baike.baidu.com/item/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/529408?fr=aladdin`

百度:01背包 https://baike.baidu.com/item/01%E8%83%8C%E5%8C%85/4301245?fr=aladdin

最近一直在制作个人博客,做好了会分享做法,请大家多多支持

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值