【背包问题】c语言

【背包问题】列有一堆物品S=(a1,a2…an),每一个物品ai都有对应的重量wi和价值vi。现在有一个背包,容量为C。现在要选择物品装入背包,所选物品重量不能超过背包容量,并使得背包里物品价值最大。与0-1背包不同的是,可以对物品进行分割,即可以只选取物品ai的一部分装入背包。 将物品按照单位价值大小排序。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// 定义结构体
typedef struct {
    double value;   // 物品的价值
    double weight;  // 物品的重量
    double ratio;   // 物品的性价比
    double in;      // 物品装入背包的重量
    int index;      // 物品的编号
} Good;

// 比较函数,用于排序
int compare(const void *a, const void *b) {
    Good *goodA = (Good *)a;
    Good *goodB = (Good *)b;
    return (int)(goodB->ratio - goodA->ratio); // 降序排序
}

// 求最大价值
double knapsack(Good *goods, int n, double v) {
    // 先将货物按照性价比排序
    qsort(goods, n, sizeof(Good), compare);
    // 从性价比高的开始装入背包
    double rem = v; // 背包的剩余容量
    double sum = 0; // 背包的总价值
    for (int i = 0; i < n; i++) {
        if(rem > 0) {
            if(rem > goods[i].weight) {
                rem -= goods[i].weight;
                goods[i].in = goods[i].weight;
                sum += goods[i].value;
            } else {
                goods[i].in = goods[i].weight - rem;
                sum += rem * goods[i].ratio;
                rem = 0;
                break;
            }
        }
    }
    return sum;
}

// 主函数
int main() {
    int n; // 物品数量
    printf("请输入物品数量:");
    scanf("%d", &n);

    Good *goods = (Good *)malloc(n * sizeof(Good));
    if (goods == NULL) {
        printf("内存分配失败\n");
        return 1;
    }

    // 输入物品信息
    for (int i = 0; i < n; i++) {
        printf("请输入第%d个物品的价值:", i + 1);
        scanf("%lf", &goods[i].value);
        printf("请输入第%d个物品的重量:", i + 1);
        scanf("%lf", &goods[i].weight);
        goods[i].ratio = goods[i].value / goods[i].weight;
        goods[i].index = i + 1;
    }

    // 背包容量
    double v;
    printf("请输入背包容量:");
    scanf("%lf", &v);

    // 计算最大价值
    double max_value = knapsack(goods, n, v);
    printf("最大价值为:%.2lf\n", max_value);

    // 释放内存
    free(goods);

    return 0;
}

运行结果:

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值