小健有一家自己的商店,主营牛奶饮品,最近资金紧张,他想以尽可能低的价格进购足够的牛奶以供日常的需要。所以小健想要求助你帮他想出一个最好的节省资金的办法。 小健可以从几个农场里购买牛奶,每个农场的牛奶都有自己的价格,每天的供应量也是有限的。小健只可以从每个农场里购买整数量的牛奶,且数量要小于等于农场的最大供应量。 给你小健每天所需要的牛奶总量,以及每个农场牛奶的单价和最大供应量,请你计算一下小健最少花多少钱就可以满足自己的需求。 ps: 一定存在一个方案可以满足小健的需求。
多组输入,读入到文件末。 每组的第一行两个整数N and M. 第一个数 N (0 <= N <= 2000000) 小健每天的牛奶需求量. 第二个数 M (0 <= M <= 5000) 小健可以选择购买的农场数. 每组的第二行到M+1行:每行两个整数 Pi and Ai. Pi (0 <= Pi <= 1000)农场i的牛奶单价. Ai (0 <= Ai <= 2000000)农场i的最大供应量.
输出可以满足小健每天需求的最小钱数。
100 5 5 20 9 40 3 10 8 80 6 30
630
思路其实很简单,做数学题嘛,先把每个农场的牛奶价格由低到高作升序排列,然后开始看第一个农场有的牛奶总量够不够小健的需求,不够的话再去第二个农场买嘛,直到买够为止。 拿这道题来讲: 1、先做价格的排序(同时仍要将牛奶量与之对应)
3 10 5 20 6 30 8 80 9 40
10+20+30+40=100 也就是买到第四行的时候不必将80个全买下来,买40个就够了
因此价格就等于10 * 3 + 20 * 5 + 30 * 6 + 40 * 8 = 630
排序难点其实不在于排价格,价格从低到高排列,冒泡啊、插入啊、快排啊、都能解决,难点在于如何将价格排序的同时,将对应农场的牛奶量也进行相应的排序(因为采用的是两个数组分别存价格和牛奶量),但仔细一想,也不难。排价格数组的时候顺便把牛奶量数组的下标一改就行了。代码如下:
void sort(int* a,int* b) { for(int m = 1; m < M; m++){ int t = a[m]; int q = b[m]; for(int j=m;a[j]<a[j-1];j--){ a[j]=a[j-1]; a[j-1]=t; b[j]=b[j-1]; b[j-1]=q; } } }接下来就是简简单单的做小学数学题了。代码如下:
int deal(int N,int* P,int* A) { mon=0;//价格重置 for (int i = 0; i < M; i++) { int tmp = N < A[i]? N : A[i];//通过三目运算来择取剩余需求和农场i牛奶量之间的最小值 mon += tmp * P[i];//计算价格 N -= tmp;//重新处理剩余需求 } return mon;//最终返回所求的最低价格 }思路都一样,只是存储价格和牛奶量的方法不再局限于数组,可以使用容器vector和结构模板pair,以及不用自己实现sort函数,可以直接调用algorithm里的sort函数。(ps:当然c语言也有qsort函数,但是STL是真的香啊~)
写一个compare函数的目的主要是为了便于自己理解sort函数的第三个参数,当然不写自定义函数直接将sort的第三个参数写成lambda表达式会更方便(也更难理解嘤嘤嘤)。哦此处提醒一下,从数学上来看,sort函数是一个左边闭区间,右边开区间的域,也就是如果有一个数组a[3],用户想要给整个数组升序排序要写成sort(a,a+3),众所周知a[3]是a+2,当然用容器就不牵扯这个问题了。
bool compare(pair<int,int> a,pair<int,int> b){ return a.first < b.first;//升序排列 }不需要compare的sort长什么样呢?我明天就学lambda表达式好叭!
sort(res.begin(), res.end(),[](const pair<int, int>& cast1, const pair<int, int>& cast2){ return cast1.first < cast2.first; });