PAT甲级 1070 Mooncake (25分) python/C++ 坑点

1070 Mooncake (25分)

Mooncake is a Chinese bakery product traditionally eaten during the Mid-Autumn Festival. Many types of fillings and crusts can be found in traditional mooncakes according to the region's culture. Now given the inventory amounts and the prices of all kinds of the mooncakes, together with the maximum total demand of the market, you are supposed to tell the maximum profit that can be made.

Note: partial inventory storage can be taken. The sample shows the following situation: given three kinds of mooncakes with inventory amounts being 180, 150, and 100 thousand tons, and the prices being 7.5, 7.2, and 4.5 billion yuans. If the market demand can be at most 200 thousand tons, the best we can do is to sell 150 thousand tons of the second kind of mooncake, and 50 thousand tons of the third kind. Hence the total profit is 7.2 + 4.5/2 = 9.45 (billion yuans).

Input Specification:

Each input file contains one test case. For each case, the first line contains 2 positive integers N (≤1000), the number of different kinds of mooncakes, and D (≤500 thousand tons), the maximum total demand of the market. Then the second line gives the positive inventory amounts (in thousand tons), and the third line gives the positive prices (in billion yuans) of N kinds of mooncakes. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the maximum profit (in billion yuans) in one line, accurate up to 2 decimal places.

Sample Input:

3 200
180 150 100
7.5 7.2 4.5

Sample Output:

9.45

题目大意

要卖月饼获得最大利润。输入如下:

  • 第一行输入两个整数N和D:N种月饼,D千吨市场需求(意味着总共只能卖D千吨的月饼)。
  • 第二行输入N个数,记为Q_{0},Q_{1},...,Q_{N-1}:表示N种月饼按序列出对应的原材料总库存(千吨)。
  • 第三行输入N个数,记为P_{0},P_{1},...,P_{N-1}:表示N种月饼按序列出对应的总利润(十亿元)。

要求是卖的月饼总量不能超过D千吨,总利润最大化的利润是多少(十亿元),输出该数保留两位小数。

注意点

  • P_{i}\div Q_{i} 才是i号月饼的单利润(十亿元每千吨)。
  • 第二行的每种月饼库存不一定是整数
  • 有可能所有月饼的库存之和也小于总市场需求D

解题思路

采用贪心思维,优先“卖出”单利润高的月饼,直到卖光月饼或者卖出市场需求的总量的月饼。

用变量ans来记录最大利润,初始为0.0(浮点数)。

按每种月饼的单利润p_{i}=\frac{P_{i}}{Q_{i}}非增排序(降序),再遍历每种月饼,记当前遍历的是i号月饼,则循环内:

  1. 当时,说明卖光i号月饼也不会超出市场需求,那就卖光,即ans自增P_{i},同时D自减Q_{i}
  2. 否则,说明i号月饼只能卖D(千吨)。那就只卖D(千吨)即ans自增p_{i}\cdot D,因为市场饱和了,不能再卖下一种月饼了,故跳出循环。

也有可能卖光N种月饼的库存也达不到市场需求的D(千吨),遍历完N种月饼自然跳出循环。

所有的变量,除了N种月饼的N逻辑上是整数之外,都采用浮点数!否则就会有坑爹的样例无法通过。


参考代码

c++版

#include
#include
#define FOR(i, s, e) for (int i = (s); i<(e); ++i)
using namespace std;
const size_t maxN = 1010;
struct INFO {
	double quantity=0;      //题目没说一定是整数!故用浮点数!
	double totol_price = 0;
	double price=0;
	bool operator<( const INFO&r)const {
		return price > r.price;
	}
};
INFO A[maxN];
int main() {
	int N; double D, ans = 0;
	scanf("%d %lf", &N, &D);
	FOR(i, 0, N) {
		scanf("%lf", &A[i].quantity);
	}
	FOR(i, 0, N) {
		scanf("%lf", &A[i].totol_price);
		A[i].price = A[i].totol_price / A[i].quantity;
	}
	sort(A, A + N);
	FOR(i, 0, N) {
		if (D > A[i].quantity) {
			ans += A[i].totol_price;
			D -= A[i].quantity;
		}else {
			ans += D*A[i].price;
			break;
		}
	}
	printf("%.2lf\n", ans);
	//system("pause");
	return 0;
}

python3版

D=float(input().split()[1])
ans=0.0
for Qi,Pi in sorted(zip(*(map(float,input().split()) for i in range(2))),key=lambda e:e[0]/e[1]):
    if D>Qi:
        D-=Qi
        ans+=Pi
    else:
        ans += Pi * D/Qi
        break
print("%.2f"%(ans))

 

你可能感兴趣的:(PAT甲级,贪心算法)