USACO section1.3 Mixing Milk
2014-07-19 22:07
351 查看
section 1.3 讲的是贪心算法(greedy algorithm),贪心算法虽然不一定普遍适用,但是对于某些问题,如果确定贪心算法对问题的解法是对的,那么使用贪心算法是非常有效的。本节的几个题目都需要使用贪心算法来求解。本文是本节的第一个问题 Mixing Milk
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.
本题使用贪心算法的解决思路是,将提供牛奶的奶农按他们提供的单价排序,从单价最低的奶农手里收购牛奶,如果提供的牛奶不够满足需求量,则继续向单价第二低的奶农手里收购,如此依次收购直到满足需求的量。
由于涉及到对奶农按给出的单价排序,这里可以使用STL中的数据结构map,以奶农给出的单价作为map的第一个值,提供的牛奶量作为第二个值,由于map的特性,完成数据输入的同时,已经完成了按单价从小到大排序的过程。另外,由于可能有多个奶农以相同的单价提供,可以将以相同单价提供牛奶的奶农看成一个奶农,将他们提供的牛奶量累加起来。这样,我们只需要根据牛奶单价进行区分。
这份答案里,使用了快速排序对输入数据进行了排序,复杂度为O(nlgn),官方下面给出的另一种方法则没有使用快速排序,而是直接建立一个大小为MAXPRICE的数组,数组按价格取下标,值即为相应价格的牛奶量。这个方法与本文使用map的方法类似,避免了排序的过程,复杂度为线性的,相比原先排序法降低了不少。
原文
Mixing Milk
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.
PROGRAM NAME: milk
INPUT FORMAT
Line 1: | Two integers, N and M. The first value, N, (0 <= N <= 2,000,000) is the amount of milk that Merry Milk Makers wants per day. The second, M, (0 <= M <= 5,000) is the number of farmers that they may buy from. |
Lines 2 through M+1: | The next M lines 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. |
SAMPLE INPUT (file milk.in)
100 5 5 20 9 40 3 10 8 80 6 30
OUTPUT FORMAT
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 OUTPUT (file milk.out)
630
分析
本题题意非常简单,从若干个奶农手里收购牛奶,直到达到需要的牛奶量,每个奶农能够的提供的牛奶量和单价都不同,求如何购买使得最终花费钱最少。本题使用贪心算法的解决思路是,将提供牛奶的奶农按他们提供的单价排序,从单价最低的奶农手里收购牛奶,如果提供的牛奶不够满足需求量,则继续向单价第二低的奶农手里收购,如此依次收购直到满足需求的量。
由于涉及到对奶农按给出的单价排序,这里可以使用STL中的数据结构map,以奶农给出的单价作为map的第一个值,提供的牛奶量作为第二个值,由于map的特性,完成数据输入的同时,已经完成了按单价从小到大排序的过程。另外,由于可能有多个奶农以相同的单价提供,可以将以相同单价提供牛奶的奶农看成一个奶农,将他们提供的牛奶量累加起来。这样,我们只需要根据牛奶单价进行区分。
提交代码
/* ID: PROG: milk LANG: C++ */ #include <fstream> #include <algorithm> #include <vector> #include <string> #include <math.h> #include <map> #include <iostream> using namespace std; int main() { int N,M; ifstream ifile("milk.in"); ifile >> N >> M; map<int,int> data; for (int i=0;i!=M;i++) { int a,b; ifile >> a >> b; if(data.find(a) == data.end()) data[a] = b; else data[a] += b; } int cost=0; int total=0; for (map<int,int>::iterator itr = data.begin();itr != data.end();++itr) { if(total + itr->second <= N) { cost += itr->second * itr->first; total += itr->second; } else { cost += itr->first * (N - total); break; } } ofstream fout("milk.out"); fout << cost << endl; return 0; }
提交结果
TASK: milk LANG: C++ Compiling... Compile: OK Executing... Test 1: TEST OK [0.000 secs, 3496 KB] Test 2: TEST OK [0.005 secs, 3496 KB] Test 3: TEST OK [0.005 secs, 3496 KB] Test 4: TEST OK [0.005 secs, 3496 KB] Test 5: TEST OK [0.008 secs, 3496 KB] Test 6: TEST OK [0.019 secs, 3496 KB] Test 7: TEST OK [0.011 secs, 3496 KB] Test 8: TEST OK [0.016 secs, 3496 KB] All tests OK.
官方给出的参考答案
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #define MAXFARMER 5000 typedef struct Farmer Farmer; struct Farmer { int p; /* price per gallon */ int a; /* amount to sell */ }; int farmcmp(const void *va, const void *vb) { return ((Farmer*)va)->p - ((Farmer*)vb)->p; } int nfarmer; Farmer farmer[MAXFARMER]; void main(void) { FILE *fin, *fout; int i, n, a, p; fin = fopen("milk.in", "r"); fout = fopen("milk.out", "w"); assert(fin != NULL && fout != NULL); fscanf(fin, "%d %d", &n, &nfarmer); for(i=0; i<nfarmer; i++) fscanf(fin, "%d %d", &farmer[i].p, &farmer[i].a); qsort(farmer, nfarmer, sizeof(farmer[0]), farmcmp); p = 0; for(i=0; i<nfarmer && n > 0; i++) { /* take as much as possible from farmer[i], up to amount n */ a = farmer[i].a; if(a > n) a = n; p += a*farmer[i].p; n -= a; } fprintf(fout, "%d\n", p); exit(0); }
这份答案里,使用了快速排序对输入数据进行了排序,复杂度为O(nlgn),官方下面给出的另一种方法则没有使用快速排序,而是直接建立一个大小为MAXPRICE的数组,数组按价格取下标,值即为相应价格的牛奶量。这个方法与本文使用map的方法类似,避免了排序的过程,复杂度为线性的,相比原先排序法降低了不少。
#include<stdio.h> #define MAXPRICE 1001 int amount_for_price[MAXPRICE]={0}; int N, M; int Cal(void); int Read(void); int main(void) { Read(); Cal(); return 0; } int Cal(void) { int i; int price_total=0; int milk_total=0; for(i=0;i<MAXPRICE;i++) { if(amount_for_price[i]) { if(milk_total+amount_for_price[i]<N) { price_total+=(i*amount_for_price[i]); milk_total+=amount_for_price[i]; } else { int amount_needed = N-milk_total; price_total+=(i*amount_needed); break; } } } { FILE* out=fopen("milk.out","w"); fprintf(out,"%d\n",price_total); fclose(out); } return 0; } int Read(void) { FILE* in = fopen("milk.in","r"); int i, price, amount; fscanf(in,"%d %d",&N,&M); for(i=0;i<M;i++) { fscanf(in, "%d %d", &(price), &(amount)); amount_for_price[price]+=amount; } fclose(in); return 0; }
THE END
相关文章推荐
- 【USACO】【贪心】Section1.3 Mixing Milk 题解
- USACO-section 1.3 Mixing Milk[贪心]
- USACO Section 1.3 : Mixing Milk
- USACO Section 1.3 Mixing Milk 解题报告
- USACO - Chapter1 Section 1.3 - Mixing Milk
- USACO-Section1.3 Mixing Milk
- USACO-Section 1.3 Mixing Milk[...]
- USACO Section1.3 Mixing Milk
- USACO Section 1.3 Mixing Milk
- USACO-Section1.3 Mixing Milk [贪心]
- USACO-Section 1.3 Mixing Milk(贪心)
- USACO-Section1.3 Mixing Milk【贪心算法】
- USACO-Section1.3 Mixing Milk
- USACO-Section 1.3 Prime Cryptarithm(枚举)
- USACO-Section1.3 Dual Palindromes (进制转换和回文数)
- USACO-Section1.3 Barn Repair
- USACO 1.3 Mixing Milk(贪心)
- 【贪心】Mixing Milk 混合牛奶 milk (Usaco_Training 1.3)
- USACO Section1.3 Barn Repair 解题报告
- 题目-[USACO1.3]混合牛奶 Mixing Milk