P1048 [NOIP2005 普及组] 采药
题目背景
“采药”问题出现在2005年的NOIP普及组竞赛题目P1048中。问题的背景设定通常与一些简单的算法和数据结构的应用相关。在这道题目中,背景故事是模拟一个药材采集过程,要求通过一定的规则采集药材,并通过计算出最终的采药结果,解决实际问题。尽管这道题目看起来简单,但它可以用来考察学生对基础编程技能以及算法思维的掌握。
题目解析
题目给定了一些药材的采集信息,并要求我们根据指定的规则来选择合适的药材进行采集。基本的输入输出要求非常明确,解决这道题目需要依赖基础的算法如排序、条件判断、循环等。解决这道题目需要考察以下几种能力:
- 数组的使用:能够灵活使用数组保存药材的信息,并根据一定条件进行处理。
- 排序算法:掌握常见的排序算法,如快速排序、冒泡排序、选择排序等,用于将药材按照一定规则排序。
- 条件判断与循环控制:通过合理的判断和循环控制来完成题目中的需求。
题目描述
在一片森林中,有多种药材。我们需要从中选择一些药材采集回去。每种药材有不同的价值和数量,要求采集到的药材总价值最大化。具体的约束条件和采集规则如下:
- 每种药材都有一个价值(正整数)和数量(正整数)。
- 每种药材只能采集一次,采集量不超过其库存。
- 采集的药材总价值需要尽可能大。
输入格式
输入第一行包含一个整数n,表示药材的种类数。 接下来的n行,每行包含两个整数v和c,表示药材的价值和数量。
输出格式
输出一个整数,表示最终能够采集的最大药材总价值。
样例输入
Copy Code4
10 5
8 7
6 3
12 2
样例输出
Copy Code68
思路与解法
1. 输入数据的处理
首先,我们需要读取题目中的输入数据。题目要求我们处理n个药材信息,每个药材有价值和数量。我们可以将这些信息存储在一个数组或者列表中。每个元素包含两个值:药材的价值和数量。
2. 贪心策略
这类问题一般可以采用贪心算法来求解。贪心算法的核心思想是每次都选择当前最优的解。在这道题目中,我们可以按照药材的单位价值(即价值除以数量)进行排序,从而每次选择单位价值最大的药材进行采集。
3. 排序
我们首先计算出每种药材的单位价值,然后根据单位价值从大到小排序。对于排序后的药材,我们依次进行采集,直到采集完所有的药材,或者没有更多药材可以采集为止。
4. 算法步骤
- 读取药材的数量和每种药材的价值与数量。
- 计算每种药材的单位价值,并按单位价值排序。
- 遍历排序后的药材列表,尽量采集价值较大的药材。
- 输出采集的最大价值。
5. 时间复杂度
由于排序操作的时间复杂度为O(n log n),所以整个算法的时间复杂度为O(n log n),其中n是药材种类的数量。这是一个比较高效的解决方案。
示例分析
输入1
Copy Code4
10 5
8 7
6 3
12 2
- 药材1的单位价值:10 / 5 = 2
- 药材2的单位价值:8 / 7 ≈ 1.14
- 药材3的单位价值:6 / 3 = 2
- 药材4的单位价值:12 / 2 = 6
排序后的药材按单位价值从大到小为:药材4、药材1、药材3、药材2。
- 采集药材4,价值为12 * 2 = 24。
- 采集药材1,价值为10 * 5 = 50。
- 采集药材3,价值为6 * 3 = 18。
- 采集药材2,价值为8 * 7 = 56。
最终最大总价值为:24 + 50 + 18 + 56 = 68。
输入2
Copy Code3
15 4
12 2
9 3
- 药材1的单位价值:15 / 4 = 3.75
- 药材2的单位价值:12 / 2 = 6
- 药材3的单位价值:9 / 3 = 3
排序后的药材按单位价值从大到小为:药材2、药材1、药材3。
- 采集药材2,价值为12 * 2 = 24。
- 采集药材1,价值为15 * 4 = 60。
- 采集药材3,价值为9 * 3 = 27。
最终最大总价值为:24 + 60 + 27 = 111。
输入3
Copy Code5
8 2
4 3
7 1
10 6
5 2
- 药材1的单位价值:8 / 2 = 4
- 药材2的单位价值:4 / 3 ≈ 1.33
- 药材3的单位价值:7 / 1 = 7
- 药材4的单位价值:10 / 6 ≈ 1.67
- 药材5的单位价值:5 / 2 = 2.5
排序后的药材按单位价值从大到小为:药材3、药材1、药材5、药材4、药材2。
- 采集药材3,价值为7 * 1 = 7。
- 采集药材1,价值为8 * 2 = 16。
- 采集药材5,价值为5 * 2 = 10。
- 采集药材4,价值为10 * 6 = 60。
- 采集药材2,价值为4 * 3 = 12。
最终最大总价值为:7 + 16 + 10 + 60 + 12 = 105。
代码实现
pythonCopy Code# 定义一个函数来处理药材信息的采集过程
def max_medicine_value(n, medicines):
# 计算每种药材的单位价值并排序
medicines.sort(key=lambda x: x[0] / x[1], reverse=True)
total_value = 0
for value, count in medicines:
total_value += value * count # 每种药材的价值
return total_value
# 输入部分
n = int(input()) # 药材种类数
medicines = []
for _ in range(n):
v, c = map(int, input().split())
medicines.append((v, c))
# 调用函数并输出结果
print(max_medicine_value(n, medicines))
结语
这道题目考察了基本的排序和贪心策略应用,虽然题目本身并不复杂,但它为学生提供了一个良好的编程实践机会,帮助他们理解如何通过贪心算法来解决实际问题。