动态规划详解(3)——易错点以及经典例题

48 篇文章 0 订阅
17 篇文章 0 订阅

虽然上一篇文章说了完结了,但经过高人指点,还需要出个第三期

言归正传

首先,我们先来说说易错点

总结了以下几点:

  1. 子问题重叠性,在使用min或max时,要根据题目决定是否将目前的状态假如,此易错点在上一篇文章已经说过,大家可以回看一下

  1. 数组的下标,我们正常使用c++都是从1开始,但是数组的开始是0.

  1. 初始化,有时不能简单的初始化为0,有时需要最大化,有时需要特殊值。而且f[0]这个位置也要考虑到

  1. for循环边界,有的题就是简单的1-n等等,到有的初始值不一样,所以要格外注意

  1. 就是数组大小,题目中也许有多个数,但是数组的大小一定要注意,有时就会爆了

本蒟蒻找的易错点就是这些,如果还有其他的,请各位佬评论区为蒟蒻补充(doge)

现在来说说经典例题

上次说的斐波那契就不讲了

  1. 开心的金明(P1060)

因为字体不是正规的,全都是问号,所以就上截屏了

输入输出样例
输入 #1
1000 5
800 2
400 5
300 5
400 3
200 2
输出 #1
3900

如果你刷了很多的动态规划题,你就会发现

金明的事儿真的好多真的很好

这道题属于是01背包题

01背包是啥?

不错我前面确实没讲给忘了

01背包就是n个物品,每个物品可能会有价值和价格

但是只有m元钱,问能达到最大价值,这里的最大价值有时不光是相加,因题而异

思想:

每个物品有两种情况:

  1. 不买

状态定义:f[i]代表i元钱能买的最大价值

初始化:w[i]*=v[i](价值算法,见题目)

状态转移方程:

重中之重

两层循环,i从1到n代表n个物品,j从1到v[i],遍历花多少钱

f[j]=max(f[j],f[j-v[i]]+w[i])

f[j-v[i]]代表买第j个物品之前的最大价值,买完后加上第j个价值

AC代码:

#include<iostream>
#include<algorithm>
using namespace std;
int w[30],v[30],f[50000];
int n,m;
int main(){
    cin>>m>>n;
    for(int i=1;i<=n;i++){
        cin>>v[i]>>w[i];
        w[i]*=v[i];
    }
    for(int i=1;i<=n;i++){
        for(int j=m;j>=v[i];j--){
            if(j>=v[i]){
                f[j]=max(f[j],f[j-v[i]]+w[i]);
            }
        }
    }
    cout<<f[m]<<endl;
    return 0;
}

今天的动态规划讲解到这里就结束了

出不出(4)现在说不准()

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值