有关背包问题

本文介绍了背包问题的定义及其不同类型,着重讨论了0/1背包问题、完全背包问题和多重背包问题,并阐述了动态规划在求解这些问题中的应用,以及基本的动态规划思想:状态定义、状态转移、初始化和计算顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是背包问题

背包问题是:一类组合优化的问题,它可以描述为:给定一组物品,每种物品都有自己的重量和价值,在限定的总重量内,如何选择这些物品放入背包,以使得背包内物品的总价值最大。背包问题根据其特定的约束条件和规则,可以分为几种不同的类型,其中最著名的包括0/1背包问题、完全背包问题和多重背包问题。

1. 0/1背包问题

在0/1背包问题中,每种物品只有一件,可以选择放入或不放入背包,因此称为0/1背包问题。目标是在不超过背包最大重量限制的前提下,最大化背包内物品的总价值。

例题P1048 [NOIP2005 普及组] 采药  https://www.luogu.com.cn/problem/P1616

分析:解决问题的关键是找到动态转移方程dp[i][j] max(dp[i - 1][j - w[i]] + val[i], dp[i - 1][j])

#include <stdio.h>

int w[105], val[105];
int dp[105][1005];

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

int main() {
    int t, m;
    scanf("%d%d", &t, &m); // 读入背包总容量和物品数量
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &w[i], &val[i]); // 读入每个物品的重量和价值
    }

    // 动态规划求解0/1背包问题
    for (int i = 1; i <= m; i++) {
        for (int j = t; j >= 0; j--) {
            if (j >= w[i]) {
                dp[i][j] = max(dp[i - 1][j - w[i]] + val[i], dp[i - 1][j]);
            }
            else {
                dp[i][j] = dp[i - 1][j];
            }
        }
    }

    printf("%d", dp[m][t]); // 输出最大价值
    return 0;
}

2. 完全背包问题

与0/1背包问题不同,完全背包问题允许每种物品有无限件可用。也就是说,只要背包的容量允许,你可以放入任意数量的某种物品。同样的目标是最大化背包内物品的总价值。

例题 P1616 疯狂的采药https://www.luogu.com.cn/problem/P1616
#include <stdio.h>

int w[105], val[105];
int dp[1005]; 

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

int main() {
    int t, m;
    scanf("%d%d", &t, &m); // 读入背包总容量和物品数量
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &w[i], &val[i]); // 读入每个物品的重量和价值
    }

    // 动态规划求解完全背包问题
    for (int i = 1; i <= m; i++) {
        for (int j = w[i]; j <= t; j++) {
            // 对于完全背包问题,当考虑加入物品i时,应该从w[i]开始遍历到t
            // 因为只有当背包容量至少为物品i的重量时,才有可能放入物品
            dp[j] = max(dp[j], dp[j - w[i]] + val[i]);
        }
    }

    printf("%d", dp[t]); // 输出最大价值
    return 0;
}

3. 多重背包问题

多重背包问题是0/1背包问题和完全背包问题的一种泛化形式。在多重背包问题中,每种物品有限定的数量,不是只有一件,也不是无限件。目标依然是在背包容量限制下,最大化总价值。

背包问题的求解

背包问题可以通过动态规划、贪心算法等方法求解。动态规划是最常用的方法之一,特别适合解决这类优化问题。它通过将问题分解成更小的子问题,并找出子问题间的依赖关系,逐步构建最终解决方案。

动态规划求解背包问题的基本思想:

  • 状态定义:定义一个状态表示函数,通常是一个二维数组或一维数组,用来记录达到某种状态时的最优解(最大价值)。
  • 状态转移:找出状态之间的转移关系,即如何从一个或多个已知状态推导出新的状态。
  • 初始化:确定初始状态,即在一开始时背包的状态。
  • 计算顺序:确定状态计算的顺序,保证在计算当前状态时,所依赖的状态已经被计算过。
  • 结果输出:根据定义的状态表示函数,输出最终的最优解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值