本系列将分享十一月在marscode上遇到的比较有意思的题目供同学们交流分享。
话不多说,接下来看题:
问题概述
小 C 在一家有n道菜的饭馆点菜,每道菜有价格ai以及是否含蘑菇的标识si( si='1'表示含蘑菇,否则不含)。小 C 要选 k 道菜,需满足所选菜中最多只有 m 道菜含蘑菇,同时要使总价格尽可能低,求满足条件下的最小总价格,若无法按要求选菜则输出 -1。
样例1:
输入:
s = "001", a = [10, 20, 30], m = 1, k = 2
输出:30
样例2:
输入:
s = "111", a = [10, 20, 30], m = 1, k = 2
输出:-1
样例3:
输入:
s = "0101", a = [5, 15, 10, 20], m = 2, k = 3
输出:30
具体解决思路
思考解决方案时就必须考虑具体所要使用的算法、结构体、函数等。
结构体定义
typedef struct {
int price;
int hasMushroom;
} Dish;
定义了一个名为 Dish 的结构体,用于存储每道菜的价格(price)和是否含有蘑菇(hasMushroom,1 表示含有,0 表示不含有)的信息。
比较函数
int compare(const void * a, const void * b){
Dish * dishA = (Dish *)a;
Dish * dishB = (Dish *)b;
return dishA->price - dishB->price;
}
这个函数是用于 qsort 函数的比较回调函数。它接受两个指针 a 和 b,将它们转换为 Dish 结构体指针后,通过比较两个结构体中菜品价格的差值来确定排序顺序,使得菜品按照价格升序排列。
计算最小价格函数
int calculateMinPrice(Dish * dishes, int n, int k, int m) {
qsort(dishes, n, sizeof(Dish), compare);
int minPrice = -1;
int foundValidCombination = 0;
for (int i = 0; i <= n - k; i++)
{ int mushroomCount = 0; int totalPrice = 0;
for (int j = i; j < i + k; j++)
{ if (dishes[j].hasMushroom) { mushroomCount++; }
totalPrice += dishes[j].price;
}
if (mushroomCount <= m) {
foundValidCombination = 1; if (minPrice == -1 || totalPrice < minPrice) { minPrice = totalPrice; }
}
}
return minPrice;
}
- 首先,使用
qsort函数根据定义的比较函数compare对菜品数组dishes按照价格进行排序,这样在后续枚举组合时,可以更容易地找到价格较低的组合。 - 然后,初始化
minPrice为 -1,表示尚未找到满足条件的组合时的初始值,foundValidCombination为 0,用于标记是否找到过满足条件的组合。 - 接下来,通过两层循环枚举从
n道菜中选k道菜的所有可能组合。外层循环控制起始位置,内层循环计算当前组合的含蘑菇菜品数量(mushroomCount)和总价格(totalPrice)。 - 最后,如果当前组合满足含蘑菇菜品数量不超过
m的条件,就更新foundValidCombination标记为 1,并根据情况更新minPrice为更小的总价格。函数最后返回minPrice,即满足条件的最小总价格。
最终主函数代码如下
int main() {
int n, k, m; scanf("%d %d %d", &n, k, m);
Dish * dishes = (Dish *)malloc(n * sizeof(Dish));
for (int i = 0; i < n; i++) {
scanf("%d %d", &dishes[i].price, &dishes[i].hasMushroom);
}
int result = calculateMinPrice(dishes, n, k, m);
printf("%d\n", result);
free(dishes);
return 0;
}
不难看出,本解法使代码凝练、清晰的关键步骤:
结构体定义
定义 Dish 结构体,包含菜品价格 price 和是否含蘑菇 hasMushroom 两个成员,用于集中存储每道菜的关键信息,方便后续操作。
比较函数
作为 qsort 的回调函数,依据菜品价格实现对菜品数组的升序排序,为后续查找满足条件的低价组合奠定基础。
计算最小总价格函数
排序准备:先使用 qsort 依据上述比较函数对菜品数组排序。
组合枚举与统计:通过双层循环枚举选 k 道菜的所有组合,内层循环统计每个组合中含蘑菇菜品数量及总价格。
条件判断与更新:若组合满足含蘑菇菜品不超 m 道的条件,根据情况更新最小总价格及标记是否找到有效组合,最终返回最小总价格。
同学们还应多多学习,在今后的刷题训练一步一步地体会、总结反思这一代码优化思想,方法论。