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日

相关文章

  • CLion安装、汉化、配置图文详解

    首先我们来讲一下如何安装CLion。 CLion安装 下载 CLion可在官方网站(https://www.jetbrains.com/clion/download)上进行下载,选择合适的操作系统对应的版本进行下载。下载完成后,可以解压到指定目录。 安装 解压完成后,在终端进入解压后的目录,输入./bin/clion.sh 启动,然后就是选择默认安装路径,应…

    C 2023年5月22日
    00
  • C++有限状态机实现计算器小程序

    C++有限状态机实现计算器小程序攻略 1. 什么是有限状态机? 有限状态机(FSM, Finite State Machine)是一种数学模型,它可以通过状态转移来描述一个系统的行为。在有限状态机中,系统从一个状态转移至另一个状态,这是通过一些输入(input)或者事件(event)来触发的。有限状态机包含三个要素: 状态集合 输入集合 状态转移 2. 怎样…

    C 2023年5月23日
    00
  • C语言实现教务管理系统

    C语言实现教务管理系统攻略 什么是教务管理系统? 教务管理系统是用于学校管理各类学生信息、教师信息、考试信息、课程信息等的一款软件。它能够提供方便快捷的教务事务处理,节约时间和劳动力,提高工作效率和精度。 C语言实现教务管理系统的必要性 C是一种高效的、跨平台的编程语言,它在系统开发、游戏开发等领域广泛应用。而在实现教务管理系统这样的软件开发中,C语言具有更…

    C 2023年5月23日
    00
  • C语言菜鸟基础教程之判断

    下面是针对“C语言菜鸟基础教程之判断”进行详细讲解的完整攻略。 什么是判断语句? 判断语句是编程中非常重要的控制语句之一,它能够根据指定条件的真假来完成不同的操作。在C语言中,判断语句主要有两种:if语句和switch语句。 if语句 if语句是C语言中最为基础的判断语句,它的基本语法如下: if (condition) { statement1; } el…

    C 2023年5月22日
    00
  • C语言kmp算法简单示例和实现原理探究

    C语言KMP算法简单示例和实现原理探究 概述 KMP算法是一种字符串匹配算法,它能在O(n+m)的时间复杂度内匹配文本串和模式串。与简单的暴力匹配算法相比,它的时间复杂度更低。 实现原理 暴力匹配算法 在了解KMP算法之前,我们先来看一下暴力匹配算法,这是最简单的字符串匹配算法。 暴力匹配算法的实现原理是:假设文本串为T,模式串为P,从T的第一个字符开始,依…

    C 2023年5月22日
    00
  • C语言实现简单的贪吃蛇游戏的示例代码

    下面是详细的讲解“C语言实现简单的贪吃蛇游戏的示例代码”的攻略。 1. 前置知识 在开始编写贪吃蛇游戏代码之前,我们需要了解一些基本的C语言知识,包括:基本数据类型、条件语句、循环语句、函数、数组等等。如果对这些基础知识掌握不够熟练,建议先学习一下。 2. 游戏规则设计 在编写代码之前,我们需要明确游戏的规则和基本操作,例如: 蛇的移动方式:蛇可以向上、下、…

    C 2023年5月24日
    00
  • Java日常练习题,每天进步一点点(38)

    Java日常练习题,每天进步一点点(38) 题目描述 定义父类People,创建子类VIP,编写一个测试类Test,在测试类里面,创建两个People的对象和两个VIP的对象并赋值,然后分别调用他们的属性与方法 题目思路 本题考察了Java面向对象的三大特性:封装、继承、多态。People作为父类,VIP作为子类,VIP拥有自己的新属性和方法。在测试类中,定…

    C 2023年5月23日
    00
  • C++中函数指针详解及代码分享

    关于“C++中函数指针详解及代码分享”的完整攻略,我为大家总结如下: 1. 什么是函数指针? 函数指针是一个指向函数的指针变量。函数指针可以像普通函数一样被调用,其语法形式为: 返回值类型 (*指针变量名)(参数列表); 其中,指针变量名可以被赋值为相同参数列表和返回类型的函数地址。可以使用函数指针来传递函数作为参数、实现回调函数等。 举个例子,假如我们有一…

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