31. 动态规划
一、什么是动态规划
动态规划的基本原理是将问题分解成若干个子问题,通过解决子问题并将结果保存起来,从而避免重复计算,提高算法的效率。动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解,每一个解都对应于一个值,希望找到具有最优值的解。
动态规划算法与分治法类似,其基本思想也是 将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的,即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解。
动态规划可以通过 填表 的方式来逐步推进,得到最优解。
二、背包问题
背包问题(Knapsack Problem)是一种组合优化的 NP 完全问题。该问题的描述是:给定一组物品,每种物品都有自己的重量和价格,在限定的总重量内,如何选择物品才能使得物品的总价格达到最高。这个问题得名于如何选择最合适的物品放入一个给定背包的场景。
假设有一个背包,容量为 4 磅,现有如下物品:
物品 | 重量 | 价值 |
---|---|---|
吉他 | 1 | 1500 |
音响 | 4 | 3000 |
电脑 | 3 | 2000 |
要求装入背包中的物体的价值最大,且重量没有超过。装入背包的物体不能重复。
#include <stdio.h>
typedef struct Good
{
char name[10];
int weight;
int value;
} Good;
void Knapsack(Good goods[], int n, int capacity);
int main(void)
{
Good goods[] = {
{"吉他", 1, 1500},
{"音响", 4, 3000},
{"电脑", 3, 2000},
};
int capacity = 4;
int n = sizeof(goods) / sizeof(Good);
Knapsack(goods, n, capacity);
return 0;
}
/**
* @brief 0-1背包问题的动态规划算法
*
* @param goods 物品数组
* @param n 物品种类数
* @param capacity 背包容量
*/
void Knapsack(Good goods[], int n, int capacity)
{
// v[i][j]表示在前i个物品中能够装入容量为j的背包的最大价值
int v[n][capacity+1];
int path[n][capacity+1];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < capacity + 1; j++)
{
v[i][j] = 0;
path[i][j] = 0;
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < capacity + 1; j++)
{
// j表示当前的背包容量
if (goods[i].weight > j) // 新增的物品重量大于背包容量
{
// i==0,表示是第一个物品,没有前一个物品,价值为0
// v[i - 1][j]表示前i-1个物品装入容量为j的背包的最大价值
v[i][j] = (i == 0) ? 0 : v[i - 1][j];
}
else // 新增的物品重量小于等于背包容量
{
// i==0,表示是第一个物品,没有前一个物品,价值为物品价值
if (i == 0)
{
v[i][j] = goods[i].value;
path[i][j] = 1;
continue;
}
// j - goods[i].weight表示去除当前物品的重量后背包剩余的容量
// v[i - 1][j - goods[i].weight]表示前i-1个物品装入容量为(j - goods[i].weight的背包的最大价值
// v[i - 1][j]表示前i-1个物品装入容量为j的背包的最大价值
if (v[i - 1][j - goods[i].weight] + goods[i].value > v[i - 1][j])
{
v[i][j] = v[i - 1][j - goods[i].weight] + goods[i].value;
path[i][j] = 1;
}
else
{
v[i][j] = v[i - 1][j];
}
}
}
}
for (int i = n - 1, j = capacity; i >= 0 && j > 0; i--)
{
if (path[i][j])
{
printf("%s 放入到背包\n", goods[i].name);
j -= goods[i].weight;
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南