一、 问题描述
二、算法思想
这是一个背包问题,可以使用动态规划算法来解决。具体思路如下:
- 定义一个二维数组dp,dp[i][j]表示前i个物品在背包容量为j时能获取的最大价值。
- 初始化dp数组的第一行和第一列为0,表示当只有一个物品或背包容量为0时,最大价值为0。
- 遍历每个物品i和每个背包容量j,根据以下状态转移方程更新dp数组:
- 如果物品i的重量大于背包容量j,则无法放入背包,dp[i][j] = dp[i-1][j]。
- 如果物品i的重量小于等于背包容量j,则考虑放入或不放入物品i的情况:
- 放入物品i,dp[i][j] = dp[i-1][j-weight[i]] + value[i],其中weight[i]表示物品i的重量,value[i]表示物品i的价值。
- 不放入物品i,dp[i][j] = dp[i-1][j]。
- 选择较大的值作为dp[i][j]。
- 从dp数组的最后一个元素往前遍历,根据状态转移方程可以得到装入背包的物品编号。
- 输出装入背包的物品编号。
三、代码实现
#include <stdio.h>#define MAX_ITEMS 100
#define MAX_WEIGHT 1000int max(int a, int b) {return (a > b) ? a : b;
}// 动态规划求解背包问题
void knapsack(int n, int capacity, int weights[], int values[]) {int dp[MAX_ITEMS + 1][MAX_WEIGHT + 1] = {0};int i, w;// 填表格for (i = 1; i <= n; i++) {for (w = 1; w <= capacity; w++) {if (weights[i - 1] > w) {dp[i][w] = dp[i - 1][w];} else {dp[i][w] = max(dp[i - 1][w], values[i - 1] + dp[i - 1][w - weights[i - 1]]);}}}// 回溯找出装入背包的物品int res[MAX_ITEMS];int k = n, c = capacity;int num = 0;while (k > 0 && c > 0) {if (dp[k][c] != dp[k - 1][c]) {res[num++] = k;c -= weights[k - 1];}k--;}// 输出结果for (i = num - 1; i >= 0; i--) {printf("%-d ", res[i]);}printf("\n");printf("end");
}int main() {int n, capacity;scanf("%d %d", &n, &capacity);int weights[MAX_ITEMS], values[MAX_ITEMS];for (int i = 0; i < n; i++) {scanf("%d", &weights[i]);}for (int i = 0; i < n; i++) {scanf("%d", &values[i]);}// 调用背包问题求解函数knapsack(n, capacity, weights, values);return 0;
}
执行结果
结语
如果你喜欢一匹马
不必去追,去种草
来年会有一群马向你奔来
!!!