L2-003 月饼

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

// 定义月饼结构体
typedef struct {
    double stock;  // 库存量(万吨)
    double total_price;  // 总售价(亿元)
    double unit_price;  // 单位售价(亿元/万吨)
} Mooncake;

// 比较函数,用于排序(按单位售价从高到低)
int compare(const void *a, const void *b) {
    Mooncake *m1 = (Mooncake *)a;
    Mooncake *m2 = (Mooncake *)b;
    if (m1->unit_price > m2->unit_price) return -1;  // 降序排列
    if (m1->unit_price < m2->unit_price) return 1;
    return 0;
}

int main() {
    int N, D;
    scanf("%d %d", &N, &D);  // 输入月饼种类数和市场需求量

    Mooncake mooncakes[N];  // 定义月饼数组

    // 输入每种月饼的库存量
    for (int i = 0; i < N; i++) {
        scanf("%lf", &mooncakes[i].stock);
    }

    // 输入每种月饼的总售价
    for (int i = 0; i < N; i++) {
        scanf("%lf", &mooncakes[i].total_price);
    }

    // 计算每种月饼的单位售价
    for (int i = 0; i < N; i++) {
        mooncakes[i].unit_price = mooncakes[i].total_price / mooncakes[i].stock;
    }

    // 按单位售价从高到低排序
    qsort(mooncakes, N, sizeof(Mooncake), compare);

    double max_profit = 0.0;  // 最大收益
    double remaining_demand = D;  // 剩余需求量

    // 贪心选择:优先销售单位售价高的月饼
    for (int i = 0; i < N; i++) {
        if (remaining_demand <= 0) break;  // 如果需求量已满足,退出循环

        if (mooncakes[i].stock <= remaining_demand) {
            // 如果当前月饼库存量 <= 剩余需求量,全部卖出
            max_profit += mooncakes[i].total_price;
            remaining_demand -= mooncakes[i].stock;
        } else {
            // 如果当前月饼库存量 > 剩余需求量,卖出部分
            max_profit += mooncakes[i].unit_price * remaining_demand;
            remaining_demand = 0;  // 需求量已满足
        }
    }

    // 输出最大收益,精确到小数点后 2 位
    printf("%.2f\n", max_profit);

    return 0;
}

int compare(const void *a, const void *b)

这行代码定义了一个名为 compare 的函数,它是一个 比较函数,通常用于与 C 标准库中的 qsort 函数配合使用。

1. 返回值

  • 返回值类型是 int。
  • 返回值用于指示两个元素的相对顺序:如果返回值 小于 0,表示第一个参数 a 应该排在第二个参数 b 前面。如果返回值 大于 0,表示第一个参数 a 应该排在第二个参数 b 后面。如果返回值 等于 0,表示两个参数相等,顺序不变。

2. 参数

  • 参数类型是 const void *,即 指向任意类型的常量指针。const 表示指针指向的数据是常量,不能在函数内修改。void * 是泛型指针,可以指向任意类型的数据。
  • 参数 a 和 b 分别指向需要比较的两个元素。

为什么使用 const void *

  1. 泛型设计:qsort 是一个通用的排序函数,可以对任意类型的数组进行排序。为了支持任意类型,qsort 使用 void * 作为参数类型,允许传递任意类型的指针。
  2. 安全性:const 确保比较函数不会修改指针指向的数据,保证数据的安全性。

qsort(mooncakes, N, sizeof(Mooncake), compare);

参数详解

1. mooncakes

  • 这是待排序的数组,类型是 Mooncake 结构体数组。
  • mooncakes 是数组的起始地址,传递给 qsort 时会被隐式转换为 void * 类型。

2. N

  • 这是数组 mooncakes 的元素个数。
  • 例如,如果 mooncakes 数组有 3 个月饼,则 N = 3。

3. sizeof(Mooncake)

  • 这是每个元素的大小(以字节为单位)。
  • sizeof(Mooncake) 计算 Mooncake 结构体占用的字节数。
  • 例如,如果 Mooncake 结构体包含 3 个 double 字段,则 sizeof(Mooncake) 可能是 24 字节(假设 double 占 8 字节)。

4. compare

  • 这是比较函数的指针,用于定义排序规则。
  • compare 函数的参数类型必须是 const void *,返回值必须是 int。
  • qsort 会调用 compare 函数来比较数组中的元素。

排序过程

  1. 初始化:qsort 接收数组 mooncakes、元素个数 N、元素大小 sizeof(Mooncake) 和比较函数 compare。
  2. 比较和交换:qsort 内部使用快速排序算法(或其他高效的排序算法)对数组进行排序。在排序过程中,qsort 会多次调用 compare 函数来比较数组中的元素。
  3. 排序完成:排序完成后,数组 mooncakes 中的元素会按照 compare 函数定义的规则排列。

在C语言中,结构体指针访问成员需要使用箭头运算符 ->,而结构体变量访问成员使用点运算符 .。以下是详细解释:

为什么不能将 m1->unit_price 改成 m1.unit_price?

指针与变量的区别:

m1 和 m2 是 Mooncake 类型的指针(Mooncake*),它们指向结构体的内存地址。

如果直接写 m1.unit_price,相当于试图通过指针变量(m1)直接访问成员,但指针本身并不是结构体实例,语法错误。

正确的访问方式:

指针访问成员:必须用 ->(等价于 (*m1).unit_price)。

变量访问成员:如果 m1 是结构体变量(如 Mooncake m1;),则可以用 .

用 ->:当操作对象是结构体指针时(如 Mooncake*)。

用 .:当操作对象是结构体变量时(如 Mooncake m1;)。

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务