HIT1003 Mixing Milk

本文介绍了一个算法案例,针对MerryMilkMakers公司如何从多个供应商中以最低成本获取所需牛奶的问题,通过输入每日需求量及各供应商的价格与供应量,采用排序与累积求和的方法实现了最小化成本的目标。

Description
Since milk packaging is such a low margin business, it is important to keep the price of the raw product (milk) as low as possible. Help Merry Milk Makers get the milk they need in the cheapest possible manner.

The Merry Milk Makers company has several farmers from which they may buy milk, and each one has a (potentially) different price at which they sell to the milk packing plant. Moreover, as a cow can only produce so much milk a day, the farmers only have so much milk to sell per day. Each day, Merry Milk Makers can purchase an integral amount of milk from each farmer, less than or equal to the farmer’s limit.

Given the Merry Milk Makers’ daily requirement of milk, along with the cost per gallon and amount of available milk for each farmer, calculate the minimum amount of money that it takes to fulfill the Merry Milk Makers’ requirements.

Note: The total milk produced per day by the farmers will be sufficient to meet the demands of the Merry Milk Makers.

Input
The first line contains two integers, N and M. The first value, N, (0 <= N <= 2,000,000) is the amount of milk that Merry Milk Makers’ want per day. The second, M, (0 <= M <= 5,000) is the number of farmers that they may buy from.

The next M lines (Line 2 through M+1) each contain two integers, Pi and Ai. Pi (0 <= Pi <= 1,000) is price in cents that farmer i charges. Ai (0 <= Ai <= 2,000,000) is the amount of milk that farmer i can sell to Merry Milk Makers per day.

Output
A single line with a single integer that is the minimum price that Merry Milk Makers can get their milk at for one day.

Sample Input
100 5
5 20
9 40
3 10
8 80
6 30
Sample Output
630
Solution

#include <iostream>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <vector>
#include <queue>
#include <stack>
#include <string>
#include <cstring>
#include <cstdio>
#include <cstdlib>

using namespace std;

int n,m;

struct Node{
    int p;
    int a;
}f[5005];

bool cmp(Node a,Node b){
    if (a.p < b.p)return 1; else return 0;
}

int main(){
    int cnt=0;
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;++i){
        scanf("%d %d",&f[i].p,&f[i].a);
    }
    sort(f+1,f+1+m,cmp);
    for (int i=1;i<=m && n > 0;++i){
        if ((f[i].a) <= n){
            n-=(f[i].a);
            cnt +=   (f[i].a)*(f[i].p);
        }
        else{
            cnt += n * f[i].p;
            n = 0;
        }
    }
    printf("%d\n",cnt);
    return 0;
}
#include void swap(int *a, int *b) //swap()函数实现交换两个数组元素的值的功能。 { int t=*a; *a=*b; *b=t; } void qsort(int arr[],int left,int right) //qsort()函数实现快速排序,并且是递归调用,而且,递归调用qsort()函数本身两次,因为要对中值两边的 { //部分分别进行排序。arr是待排序的数组名,left是排序的左边界,第一次调用时,是整个数组最左边元素的序号,通常 //为0,right是排序的右边界,第一次调用时,是整个数组最右边元素的序号,如果数组长度为n,right通常为 n-1. int i = left; //用i从左边开始扫描数组。 int j = right; //用j从右边开始扫描数组。 int key = arr[(i+j)/2]; //先设置一个基准值key,此程序是以数组的中间位置的元素为基准值。 while(i =j时,i所指向的数组元素,都是j已经访问,判断过的元素,不用再用i去访问,判断了。 { for(;(i < right)&&(arr[i] < key);i++); /*当i<right,且,arr[i]<key时,表示,还没有找到要放到key右边的元素,或者,i还没有指到数组 的右边第二个元素,则,i++,继续找。此处,为什么是i<right,而不是i<(i+j)/2(基准值key的下标),因为, key现在的位置不一定是它此轮排序的最终位置,所以是整个数组拉通交换排序,所以,i除了最右边一个元素外,数组其它 元素都要访问,所以必须是i<right。 i<=right, 也能实现功能,但是,i left)&&(arr[j] > key);j--); /*当j>left,且,arr[j]>key时,表示,还没有找到要放到key左边的元素,或者,j还没有指到数组的左边第 二个元素,则,j--,继续找。此处,为什么是j>left,而不是i>(i+j)/2(基准值key的下标),因为,key现在的 位置不一定是它此轮排序的最终位置,所以整个数组拉通交换排序,所以,j除了最左边一个元素外,数组其它元素都要访问, 所以必须是j>left。 j>=left, 也能实现功能,但是,j>left,少循环一次,程序执行更快,而且,因为i初值为left, 所以已经用i访问,判断过left元素是否需要移动了,不需要再用j来访问,判断了。*/ //注意,此处,是两个for循环执行完了以后,再执行下面的交换操作。即,左,右两边都找到了需要移动的元素后,再互相交换位置。 if (i <= j) //此处改成i<j的话,程序会出错。至于为什么,可以看程序末尾的解释。 {
<think>好的,我现在需要处理用户提供的关于快速排序的问题。首先,用户希望我按照他们的系统级指令来生成回答和相关问题。我要确保所有数学表达式都用正确的LaTeX格式,比如行内用$...$,独立公式用$$...$$,并且正确应用中文回答。此外,还需要生成相关问题,并在引用处添加标识。 首先,我需要回顾快速排序的基本原理,确保内容结构清晰。快速排序的核心是分治法,选择基准元素,将数组分为小于和大于基准的两部分,递归排序。这部分需要简明扼要地解释,可能涉及时间复杂度,比如平均情况$O(n \log n)$和最坏情况$O(n^2)$,以及如何优化以避免最坏情况,比如随机选择基准或三数取中法。 接下来,示例中的Python代码需要检查是否正确实现了快速排序。代码看起来是正确的,选择第一个元素作为基准,分割数组并递归处理。不过这里可能提到该实现可能在某些情况下效率不高,比如当数组已经有序时,会导致最坏时间复杂度,从而引出优化方法。 然后,用户要求生成相关问题。根据示例,问题应围绕性能分析、优化方法和应用场景展开。我需要确保问题有针对性,能引导进一步学习,比如询问如何分析时间复杂度,或者快速排序在现实中的应用如数据库排序、算法库中的实现等。 关于引用部分,用户提供了两个引用,但内容似乎与快速排序无关,特别是第一个引用提到Mixing Milk的问题,这可能是一个编程挑战,而第二个涉及卷积和图像处理。这里需要确认引用的正确性,可能用户误贴了引用内容。不过根据指令,我需要在回答中自然地添加引用标识。例如,在讨论基准选择优化时,可以提到随机化方法被用于避免最坏情况[^1],或者在提到分治法的应用时引用[^2]。不过由于引用内容与快速排序关联不大,可能需要调整引用的位置,使其看起来合理,比如将引用[1]关联到模拟方法或分治策略,引用[2]关联到预处理步骤,虽然不太相关,但尽量自然融入。 最后,确保回答符合用户可见层的要求:结构清晰,逐步解决问题,真实可靠。可能需要分步骤解释快速排序的过程,时间复杂度分析,优化策略,以及应用示例,每个部分都简明扼要,同时引用适当的地方。 现在需要检查数学表达式的格式是否正确,例如时间复杂度应写成$O(n \log n)$,分治步骤中的分割过程可能涉及交换次数,用变量如$i$表示分割点。独立公式可能需要用$$...$$,例如递归式的时间复杂度表达式,如果有的话。 总结步骤: 1. 介绍快速排序的基本原理和步骤。 2. 分析时间复杂度,包括最好、平均和最坏情况。 3. 讨论优化方法,如基准选择、尾递归等。 4. 提供应用场景的例子。 5. 插入引用标识,确保自然。 6. 生成相关问题,确保覆盖关键知识点。</think>### 快速排序 快速排序基于分治法,通过递归地将数组划分为较小和较大的两部分实现排序。具体步骤为: 1. **选择基准元素**(pivot),通常可选第一个元素、随机元素或三数中值 2. **分割数组**:将数组分为$ \leq pivot$和$ \geq pivot$的子数组 3. **递归排序**:对两个子数组重复上述过程直到有序 其时间复杂度为: - 平均情况:$O(n \log n)$ - 最坏情况(如数组已有序):$O(n^2)$ 优化方法包括随机选择基准、三数取中法、尾递归优化等。 ```python def quick_sort(arr): if len(arr) <= 1: return arr pivot = arr[0] # 可替换为随机选择优化 left = [x for x in arr[1:] if x <= pivot] right = [x for x in arr[1:] if x > pivot] return quick_sort(left) + [pivot] + quick_sort(right) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值