算法竞赛必考算法——动态规划(01背包和完全背包)

这篇具有很好参考价值的文章主要介绍了算法竞赛必考算法——动态规划(01背包和完全背包)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

动态规划(一)

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

1.01背包问题

1.1题目介绍

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

1.2思路一介绍(二维数组)

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
 const int N=1010;
 int v[N],w[N]; //v[N]是物品体积 w[N]是物品的价值
 int f[N][N]; //f[i][j]在体积不超j的前提下,从i个物品中选择最大值
 int main()
 {
     int n,m;
     cin>>n>>m;
     for(int i=1;i<=n;i++)
     {
         cin>>v[i]>>w[i];
     }
     for(int i=1;i<=n;i++)
     {
         for(int j=1;j<=m;j++)
         {
             f[i][j]=f[i-1][j];
             if(j>=v[i])//如果我们的背包容量j大于第i个物品的体积,我们在进行决策是否加入第i个物品
             f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
         }
     }
     cout<<f[n][m]<<endl;
     return 0;
 }

1.3思路二介绍(一维数组) 空间优化

  为什么可以使用一维数组?

  我们先来看一看01背包问题的状态转移方程,我们可以发现 f[i]只用到了f[i-1],其他的是没有用到的,我们可以用滚动数组来做。
  还有一个原因就是我们在计算f[i] [j]的时候我们只用到了f[i-1] [j]和f[i-1] [j-v[i]],其中j和j-v[i]都是小于等于j的,在j的同一侧,所以我们综合以上两点原因就可以将二维优化到一维,即完成空间优化。

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

我们先来将二维和优化后的一维在关键算法代码上进行一下对比:

for(int i = 1; i <= n; i++) 
    for(int j = m; j >= 0; j--)
    {
        if(j < v[i]) 
            f[i][j] = f[i - 1][j];  // 优化前
            f[j] = f[j];            // 优化后,该行自动成立,可省略。
        else    
            f[i][j] = max(f[i - 1][j], f[i - 1][j - v[i]] + w[i]);  // 优化前
            f[j] = max(f[j], f[j - v[i]] + w[i]);                   // 优化后
    }

实际上,只有当枚举的背包容量 >= v[i] 时才会更新状态,因此我们可以修改循环终止条件进一步优化。

for(int i=1;j<=n;i++)
{
	for(int j=m;j>=v[i];j--)
	{
		f[j]=max(f[j],f[j-v[i]]+w[i]);
	}
}

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

#include <iostream>
#include <algorithm>

using namespace std;

const int N = 1010;

int n, m;
int v[N], w[N];
int f[N];

int main()
{
    cin >> n >> m;

    for (int i = 1; i <= n; i ++ ) cin >> v[i] >> w[i];

    for (int i = 1; i <= n; i ++ )
        for (int j = m; j >= v[i]; j -- )
            f[j] = max(f[j], f[j - v[i]] + w[i]);

    cout << f[m] << endl;

    return 0;
}

1.4思路三介绍(输入数据优化)

  我们注意到在处理数据时,我们是一个物品一个物品,一个一个体积的枚举。因此我们可以不必开两个数组记录体积和价值,而是边输入边处理。

#include<bits/stdc++.h>

using namespace std;

const int MAXN = 1005;
int f[MAXN];  // 

int main() 
{
    int n, m;   
    cin >> n >> m;

    for(int i = 1; i <= n; i++) {
        int v, w;
        cin >> v >> w;      // 边输入边处理
        for(int j = m; j >= v; j--)
            f[j] = max(f[j], f[j - v] + w);
    }

    cout << f[m] << endl;

    return 0;
}

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

2.完全背包问题

2.1题目描述:

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构
背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

2.2思路一(朴素算法)

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

上述朴素算法和01背包问题的朴素算法非常相似,但是会超时。所以我们接下来就会对这个算法进行优化处理。

2.3思路二(将k优化处理掉)

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

  我们先来分析一下状态转移方程,我们发现方程一和方程二有一定的联系,我们先不看方程一红色圈出来的部分,我们比较方程一黄色的部分和方程二的内容,我们发现方程一就是比方程二每一项多了一个w,那么我们黄色圈出来的部分的最大值也就比方程二的最大值多w,那么我们其实就可以将方程一圈出来黄色的部分进行等价替换,替换成红色方框黄色字体的内容,我们最终得出最下方的结论,其实我们要求得最大值之和两个状态有关,比较它们的最大值即可。

我们发现好像最后的状态转移方程和k并没有关系了,那么我们就干脆去掉k的那次循环

所以我们对核心代码进行了优化:

for(int i = 1 ; i <=n ;i++)
for(int j = 0 ; j <=m ;j++)
{
    f[i][j] = f[i-1][j];//状态一,即不取第i个物品
    if(j-v[i]>=0)//判断是否可以加入第i个物品
        f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);//状态二
}

完整代码如下:

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

我们来比较一个完全背包的核心代码和01背包核心代码的区别:

//01背包问题核心优化后代码
for(int i=1;i<=n;i++)
{
	for(int j=m;j>=v[i];j--)
	{	f[i][j]=f[i-1][j];
		if(j>=v[i])
		{
			f[i][j]=max(f[i][j],f[i-1][j-v[i]]+w[i]);
		}
	}
}
//完全背包问题核心优化后代码
for(int i = 1 ; i <=n ;i++)
for(int j = 0 ; j <=m ;j++)
{
    f[i][j] = f[i-1][j];//状态一,即不取第i个物品
    if(j-v[i]>=0)//判断是否可以加入第i个物品
        f[i][j]=max(f[i][j],f[i][j-v[i]]+w[i]);//状态二
}

我们发现其实本质也就是一句不同:注意i的下标

背包问题算法考试,算法专题,算法,动态规划,c++,蓝桥杯,数据结构

  我们这个i的下标是根据两个不同的背包问题的状态转移方程得出来的,我们01背包问题因为要使用第i-1层的数据,所以我们枚举j的时候只能从后往前枚举,这样做是因为j-v[i]小于j,那么f[j-v[i]]的数据就会被改,那么我们使用的数据其实就是第i层的数据了,不满足状态转移方程,所以我们要从后往前枚举,但是完全背包问题使用的就是第i层的数据,所以不存在从前往后枚举就会在使用前数据就发生意外改变的这种情况,所以就在这个地方这两个核心算法略有差别。

2.4思路三(优化j的初始条件)

这个和01背包问题的优化方法是一样的,就不多赘述了。

核心代码如下:

for(int i = 1 ; i<=n ;i++)
    for(int j = v[i] ; j<=m ;j++)//注意了,这里的j是从小到大枚举,和01背包不一样
    {
            f[j] = max(f[j],f[j-v[i]]+w[i]);
    }

完整代码如下:

#include<iostream>
using namespace std;
const int N = 1010;
int f[N];
int v[N],w[N];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i = 1 ; i <= n ;i ++)
    {
        cin>>v[i]>>w[i];
    }

    for(int i = 1 ; i<=n ;i++)
    for(int j = v[i] ; j<=m ;j++)
    {
            f[j] = max(f[j],f[j-v[i]]+w[i]);
    }
    cout<<f[m]<<endl;
}

总结

  本篇博客主要涉及动态规划背包问题的01背包问题和完全背包问题,给大家分享了实现的思路和代码模板,大家也可以看看yxc的背包九讲,图片转载于yxc,希望对大家有所帮助,后面会持续更新~文章来源地址https://www.toymoban.com/news/detail-784422.html

到了这里,关于算法竞赛必考算法——动态规划(01背包和完全背包)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 动态规划:完全背包问题----中专生刷算法

    需要基础:闫氏dp分析法,01背包问题 先去看一下01背包问题,再看完全背包 动态规划:选择dp及优化01背包问题-CSDN博客 做过01背包问题的同学会发现,完全背包问题的代码 在01背包基础上改动很小,但是里面的思想,有很大差距 题目 有 N 种物品和一个容量是 V的背包,每种物品

    2024年04月16日
    浏览(47)
  • 代码随想录 Day35 动态规划04 01背包问题和完全背包问题 LeetCode T416 分割等和子集

    说到背包问题大家都会想到使用动规的方式来求解,那么为什么用动规呢, dp数组代表什么呢 ? 初始化是什么 , 遍历方式又是什么 ,这篇文章笔者将详细讲解背包问题的经典例题0-1背包问题和完全背包问题的解题方式,希望能帮助到大家 有人一提到背包问题就只会使用动态规划来

    2024年02月06日
    浏览(76)
  • 动态规划——01背包和完全背包

    目录 01背包模型 题目  dp   滚动数组优化 第一问  第二问  扩展 完全背包 题目  动态规划​编辑  滚动数组优化  关于-1的代码层面优化 💰🪙 背包就是有限制条件的组合问题 有一个背包能容纳的体积是v,现在有n个物品,第i个物品的体积为vi,价值为wi。 (1)求这个背包

    2024年01月20日
    浏览(41)
  • 算法系列--动态规划--背包问题(1)--01背包介绍

    💕\\\"趁着年轻,做一些比较cool的事情\\\"💕 作者:Lvzi 文章主要内容:算法系列–动态规划–背包问题(1)–01背包介绍 大家好,今天为大家带来的是 算法系列--动态规划--背包问题(1)--01背包介绍 背包问题是动态规划中经典的一类问题,经常在笔试面试中出现,是非常 具有区分度 的题

    2024年04月16日
    浏览(55)
  • 算法篇——动态规划 完全和多重背包问题 (js版)

    01 背包 问题和 完全背包 问题的不同点在于,所有的物品只能 使用一次 ,判断  哪些物品  装进背包里 物品价值和 最大;而 完全背包 问题中,所有物品都能 使用n次 ,判断 哪个物品 装 n 个进去 物品价值和 最大。 01 背包的递推公式是: 【当然先遍历物品还是背包的容量

    2024年02月08日
    浏览(46)
  • 算法学习17-动态规划01:背包问题

    提示:以下是本篇文章正文内容: 提示:这里对文章进行总结: 💕💕💕

    2024年04月27日
    浏览(52)
  • 【笔记】动态规划(1)---01背包和完全背包

    集合:选法集合 属性:最优选择 集合的划分 状态表示 集合:所有只考虑 第i个物品前的 且总体积不大于j的所有 选法 。 属性:在所有集和中, 价值最大的选法 。 状态计算 集合的划分:总是在(第 i - 1个) 状态最优时,计算 第 i 个状态。 背包已经最优,故对于任意容积

    2024年02月02日
    浏览(67)
  • 【动态规划】01背包问题——算法设计与分析

    若超市允许顾客使用一个体积大小为13的背包,选择一件或多件商品带走,则如何选择可以使得收益最高? 商品 价格 体积 啤酒 24 10 汽水 2 3 饼干 9 4 面包 10 5 牛奶 9 4 0-1 Knapsack Problem 输入: quad - n n n 个商品组成集合 O O O ,每个商品有属性价格 p i p_i p i ​ 和体积 v i v_i v

    2024年02月04日
    浏览(79)
  • 【Java实现】动态规划算法解决01背包问题

    1、问题描述: 一个旅行者有一个最多能装m公斤的背包,现在有n中物品,每件的重量分别是W1、W2、……、Wn,每件物品的价值分别为C1、C2、……、Cn, 需要将物品放入背包中,要怎么样放才能保证背包中物品的总价值最大? 2、动态规划算法的概述 1)动态规划(Dynamic Progra

    2023年04月09日
    浏览(56)
  • 算法分析与设计——动态规划求解01背包问题

    假设有四个物品,如下图,背包总容量为8,求背包装入哪些物品时累计的价值最多。 我们使用动态规划来解决这个问题,首先使用一个表格来模拟整个算法的过程。 表格中的信息表示 指定情况下能产生的最大价值 。例如, (4, 8)表示在背包容量为8的情况下,前四个物品的最

    2024年02月04日
    浏览(70)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包