动态规划方法解决0-1背包【详细代码】

#include <stdio.h>

// 比较两个整数并返回较大值的函数
int max(int a, int b) {
    return (a > b)? a : b;
}

// 使用动态规划解决0 - 1背包问题的函数
// 参数说明:
// w[]:存储各个物品重量的数组
// v[]:存储各个物品价值的数组
// n:物品的数量
// c:背包的容量
void f(int w[], int v[], int n, int c) {
    // 创建二维数组d,用于保存中间结果
    // d[i][j]表示前i个物品放入容量为j的背包中所能获得的最大价值
    // 初始化二维数组d的所有元素为0,这里数组大小为[n + 1][c + 1],方便处理边界情况(包括i = 0或j = 0的情况)
    int d[n + 1][c + 1] = {0};

    // 外层循环,遍历每个物品,从第0个物品开始(包含边界情况)到第n个物品
    for (int i = 0; i <= n; i++) {
        // 内层循环,遍历背包的不同容量,从第0个单位容量开始(包含边界情况)到第c个单位容量
        for (int j = 0; j <= c; j++) {
            // 处理边界情况:当没有物品可放(i == 0)或者背包容量为0(j == 0)时
            // 背包能获得的最大价值显然为0,所以将d[i][j]赋值为0
            if (i == 0 || j == 0) {
                d[i][j] = 0;
            } else if (w[i] > j) {
                // 如果当前物品的重量w[i]大于当前考虑的背包容量j,说明当前物品无法放入该容量的背包
                // 则当前状态下能获得的最大价值就等于前i - 1个物品放入容量为j的背包中所能获得的最大价值
                // 即保持d[i][j]的值与前一个物品状态下相同容量背包能获得的最大价值相同
                d[i][j] = d[i - 1][j];
            } else {
                // 如果当前物品的重量w[i]小于等于当前考虑的背包容量j,说明当前物品有可能放入背包
                // 此时需要在两种情况中取最大值来更新d[i][j]的值:
                // 1. 不放入当前物品,即前i - 1个物品放入容量为j的背包中所能获得的最大价值,也就是d[i - 1][j]
                // 2. 放入当前物品,此时背包容量变为j - w[i],那么能获得的价值就是当前物品的价值v[i]加上前i - 1个物品放入剩余容量背包中所能获得的最大价值d[i - 1][j - w[i]]
                d[i][j] = max(d[i - 1][j], v[i] + d[i - 1][j - w[i]]);
            }
        }
    }

    // 输出前n个物品放入容量为c的背包中所能获得的最大价值
    // 这里根据动态规划的计算结果,d[n][c]就是最终所求的最大价值
    printf("%d", d[n][c]);
}

int main() {
    // 定义数组v,用于存储各个物品的价值,数组大小为100
    int v[100];
    // 定义数组w,用于存储各个物品的重量,数组大小为100
    int w[100];

    // 定义变量n,用于存储物品的数量
    int n;
    // 定义变量c,用于存储背包的容量
    int c;

    // 从标准输入读取物品的数量n和背包的容量c
    scanf("%d %d", &n, &c);

    // 循环读取每个物品的价值和重量,并存入相应的数组v和w中
    // 这里按照顺序依次读取每个物品的重量和价值,并分别存入w[]和v[]数组中
    for (int i = 1; i <= n; i++) {
        scanf("%d %d", &w[i], &v[i]);
    }

    // 调用函数f计算并输出在给定背包容量下能获得的最大价值
    // 将存储物品重量的数组w、存储物品价值的数组v、物品数量n和背包容量c作为参数传递给函数f
    f(w, v, n, c);

    // 返回0,表示程序正常结束
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值