使用动态规划解决背包问题

问题描述: 设有一个背包可以放入的物品重量为 S,现有 n 件物品,重量分别是 w1, w2, w3,..wn. 问能否从这 n 件物品中选择若干件放入背包中,使得放入的重量之和正好为 S。 如果有满足条件的选择,则此背包有解,否则此背包问题无解。

解决方案: 一种常见的解决此问题的方法是使用动态规划。具体而言,可以定义一个二维数组 dp[i][j],其中 dp[i][j] 表示前 i 件物品中是否存在一些物品,使得它们的重量之和恰好为 j。则可以得到如下的递推式:

dp[i][j] = dp[i-1][j] || dp[i-1][j-w[i]]

其中 dp[i-1][j] 表示不选第 i 件物品时,前 i-1 件物品是否能凑出重量 j;dp[i-1][j-w[i]] 表示选第 i 件物品时,前 i-1 件物品是否能凑出重量 j-w[i],即凑出 j 的前提是凑出 j-w[i] 并加上第 i 件物品的重量。

最终的答案是 dp[n][S],即前 n 件物品是否存在一些物品,使得它们的重量之和恰好为 S。

C语言实现:

#include <stdio.h>
#include <stdbool.h>

bool solve(int n, int S, int w[]) {
    bool dp[n+1][S+1];
    for (int i = 0; i <= n; i++) {
        dp[i][0] = true;
    }
    for (int j = 1; j <= S; j++) {
        dp[0][j] = false;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= S; j++) {
            dp[i][j] = dp[i-1][j];
            if (j >= w[i]) {
                dp[i][j] = dp[i][j] || dp[i-1][j-w[i]];
            }
        }
    }
    return dp[n][S];
}

int main() {
    int n = 4, S = 7;
    int w[] = {0, 3, 4, 2, 1};
    if (solve(n, S, w)) {
        printf("This backpack has a solution.\n");
    } else {
        printf("This backpack has no solution.\n");
    }
    return 0;
}

代码解释:

  1. 函数 solve() 接收三个参数:物品数量 n,目标重量 S 以及物品重量数组 w
  2. 定义一个二维布尔数组 dpdp[i][j] 表示前 i 件物品中是否存在一些物品,使得它们的重量之和恰好为 j。
  3. 初始化 dp 数组:
    • dp[i][0] 为 true,表示前 i 件物品中总能找到一些物品,使得它们的重量之和为 0(不选任何物品)。
    • dp[0][j] 为 false,表示没有物品的情况下,无法凑出重量为 j 的组合。
  4. 遍历所有物品和所有可能的重量,根据递推公式更新 dp 数组。
  5. 最终 dp[n][S] 的值即为问题的答案:如果为 true,则背包有解,否则无解。

总结: 本文介绍了使用动态规划算法解决背包问题,并提供了 C 语言代码实现。动态规划算法可以有效地解决背包问题,因为它能够将问题分解成更小的子问题,并利用子问题的解来求解最终的答案。

C语言解决背包问题:动态规划实现

原文地址: https://www.cveoy.top/t/topic/lFr7 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录