C语言解决背包问题:动态规划实现
使用动态规划解决背包问题
问题描述: 设有一个背包可以放入的物品重量为 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;
}
代码解释:
- 函数
solve()接收三个参数:物品数量n,目标重量S以及物品重量数组w。 - 定义一个二维布尔数组
dp,dp[i][j]表示前 i 件物品中是否存在一些物品,使得它们的重量之和恰好为 j。 - 初始化
dp数组:dp[i][0]为 true,表示前 i 件物品中总能找到一些物品,使得它们的重量之和为 0(不选任何物品)。dp[0][j]为 false,表示没有物品的情况下,无法凑出重量为 j 的组合。
- 遍历所有物品和所有可能的重量,根据递推公式更新
dp数组。 - 最终
dp[n][S]的值即为问题的答案:如果为 true,则背包有解,否则无解。
总结: 本文介绍了使用动态规划算法解决背包问题,并提供了 C 语言代码实现。动态规划算法可以有效地解决背包问题,因为它能够将问题分解成更小的子问题,并利用子问题的解来求解最终的答案。
原文地址: https://www.cveoy.top/t/topic/lFr7 著作权归作者所有。请勿转载和采集!