C语言动态规划多种背包问题分析讲解

C语言动态规划多种背包问题分析讲解

背包问题介绍

背包问题是动态规划中比较常见的问题之一,特别是在算法竞赛中。

一般来说,背包问题可分为两大类:01背包和完全背包。01背包是每个物品只能用一次,而完全背包则是每个物品可以无限制使用。

这里将介绍多种背包问题的分析和具体实现。

01背包问题

问题描述

有一个容量为V的背包和N个物品,每个物品的体积为v[i],价值为w[i],求在装满背包的前提下,最大化能够获得的总价值。

分析与实现

01背包问题采用二维数组dp[i][j]记录放置前i个物品,总体积不超过j时的最大价值。

具体地,依次枚举物品i和容量j(即i和j的范围分别为[1, N] 和[1, V] ),讨论第i个物品是否放入背包中:

  1. 若第i个物品的体积大于j,则不放入,此时dp[i][j]的值应该和dp[i-1][j]相同;
  2. 若第i个物品的体积小于等于j,则可以将其放入背包中,此时dp[i][j]应该等于dp[i-1][j-v[i]] + w[i];
  3. 比较第1步和第2步中两种情况所对应的dp值,选择其中较大的值即可。

下面是C语言的实现代码:

#include <stdio.h>
#include <string.h>

#define maxn 1005

int max(int a, int b) {
    return a > b ? a : b;
}

int main() {
    int N, V;
    int v[maxn], w[maxn];
    int dp[maxn][maxn];

    scanf("%d%d", &N, &V);

    for (int i = 1; i <= N; i++)
        scanf("%d%d", &v[i], &w[i]);

    memset(dp, 0, sizeof(dp));

    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= V; j++) {
            if (j < v[i])
                dp[i][j] = dp[i - 1][j];
            else
                dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i]);
        }
    }

    printf("%d\n", dp[N][V]);

    return 0;
}

完全背包问题

问题描述

有一个容量为V的背包和N个物品,每个物品的体积为v[i],价值为w[i],每种物品都有无限个。在装满背包的前提下,最大化能够获得的总价值。

分析与实现

完全背包问题的dp数组和01背包问题一样是二维数组,但转移方程有所不同。

对于每个物品i,依次枚举背包中放入第i个物品的数目(即可能的xi,范围为[0, V/v[i]]),讨论第i个物品所能带来的价值:

  1. 若不放入第i个物品,则dp[i][j]的值应直接等于dp[i-1][j]。
  2. 若放入x个第i个物品,则dp[i][j]等于dp[i][j-xv[i]] + xw[i](这里借用前面提到的完全背包思想,将此方程写成这样)。

由此可得dp转移方程为:

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

下面是C语言的实现代码:

#include <stdio.h>
#include <string.h>

#define maxn 1005

int max(int a, int b) {
    return a > b ? a : b;
}

int main() {
    int N, V;
    int v[maxn], w[maxn];
    int dp[maxn][maxn];

    scanf("%d%d", &N, &V);

    for (int i = 1; i <= N; i++)
        scanf("%d%d", &v[i], &w[i]);

    memset(dp, 0, sizeof(dp));

    for (int i = 1; i <= N; i++) {
        for (int j = v[i]; j <= V; j++) {
            dp[i][j] = max(dp[i - 1][j], dp[i][j - v[i]] + w[i]);
        }
    }

    printf("%d\n", dp[N][V]);

    return 0;
}

示例说明

下面使用两个示例来说明上面介绍的两个问题。

示例1

输入:
4 5
1 2
2 4
3 4
4 5
输出:
9

解释:

这里有4个物品,容量为5,物品分别为1:(1,2),2:(2,4),3:(3,4),4:(4,5)。

使用01背包算法,可以得到最大价值为9,选择物品1和2。

示例2

输入:
4 5
1 2
2 4
3 4
4 5
输出:
10

解释:

这里与示例1相同,但与示例1不同的是,这里使用完全背包算法,最大价值为10,其中选择了物品2和4。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言动态规划多种背包问题分析讲解 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • MySQL 字符串拆分操作(含分隔符的字符串截取)

    下面就来详细讲解一下“MySQL 字符串拆分操作(含分隔符的字符串截取)”的完整攻略。 一、引言 在MySQL中,字符串拆分操作指的是将一个字符串按照指定的字符分隔后,将其拆分成多个子字符串,并分别保存到一个数组或者表中。常见的字符串拆分操作有用逗号、空格等分隔符将一组字符串拆分成多个子字符串。 在字符串拆分的操作中,很常见的一种需求是一个含有分隔符的字符串…

    C 2023年5月23日
    00
  • JavaScript对象拷贝与Object.assign用法实例分析

    JavaScript对象拷贝与Object.assign用法实例分析 在JavaScript编程中,对象拷贝是一项非常重要的任务,因为我们经常需要在代码中使用对象,但由于JavaScript对象的引用特性,往往原始对象会被误修改或者无意间影响其他部分代码,这时候需要做对象拷贝,保持数据的安全完整性。JavaScript的标准库提供了多种深复制或浅复制对象的拷…

    C 2023年5月22日
    00
  • c++11新增的便利算法实例分析

    C++11新增的便利算法实例分析 C++11为我们提供了许多实用的 STL 算法,其中一些算法来自 Boost 库,可以大大提高我们的编程效率。在本文中,我们将介绍 C++11 中的一些便利算法,包括 for_each(),transform() 和 sort(),并提供代码示例进行演示。 for_each() for_each() 算法允许我们对一个容器中…

    C 2023年5月22日
    00
  • Java 多层嵌套JSON类型数据全面解析

    Java 多层嵌套JSON类型数据全面解析 什么是JSON JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,也易于机器解析和生成。JSON是一种完全独立于语言的数据交换格式,但是在实际应用中,JSON常常以字符串的形式进行传输。 解析JSON 在Java中要解析JSON,可以使用Jackson或者…

    C 2023年5月23日
    00
  • C语言中的分支循环其嵌套语句

    C语言中的分支循环语句是控制程序流程的重要工具,它们可以根据条件来执行不同的代码块,或者循环执行某段代码块。与此同时,C语言还支持分支循环语句的嵌套,这种语句结构可以更精细地控制程序流程,提高代码的效率和可维护性。下面是完整的攻略。 分支语句 if语句 if语句是最基本的分支语句,用来测试一个条件,如果满足条件就执行指定的代码块。 语法: if (条件) {…

    C 2023年5月23日
    00
  • FreeSWITCH添加iLBC编码及转码

    操作系统 :CentOS 7.6_x64 FreeSWITCH版本 :1.10.9 一、安装ilbc库 从第三方库里下载指定版本: git clone https://freeswitch.org/stash/scm/sd/libilbc.git 如果下载过慢,可从如下途径获取: 关注微信公众号(聊聊博文,文末可扫码)后回复 20230416 获取。 编译及…

    C语言 2023年4月17日
    00
  • C语言中如何进行异步编程?

    异步编程一般指的是在程序中同时执行多个任务,而不是等待一个任务完成后再执行下一个任务。在 C 语言中,我们可以通过多线程或者事件驱动编程来实现异步编程。 多线程 多线程是一种利用 CPU 多核特性,同时执行多个线程的技术。C 语言中可以使用 pthread 库实现多线程编程。 首先需要导入 pthread 库头文件: #include <pthread…

    C 2023年4月27日
    00
  • 利用C语言实现任务调度的示例代码

    我来讲解一下如何利用C语言实现任务调度的示例代码。 什么是任务调度 任务调度是指按照一定规则和策略,将多个任务分配给CPU或其他的计算资源。通过任务调度,不同的任务可以在合适的时候被处理,从而提高系统的效率和稳定性。 使用C语言实现任务调度的示例 下面,我将给出一个使用C语言实现任务调度的示例代码: #include <stdio.h> #inc…

    C 2023年5月22日
    00
合作推广
合作推广
分享本页
返回顶部