PAT (Advanced Level) Practice 1037 Magic Coupon (25 分) 凌宸1642
题目描述:
The magic shop in Mars is offering some magic coupons. Each coupon has an integer N printed on it, meaning that when you use this coupon with a product, you may get N times the value of that product back! What is more, the shop also offers some bonus product for free. However, if you apply a coupon with a positive N to this bonus product, you will have to pay the shop N times the value of the bonus product… but hey, magically, they have some coupons with negative N’s!
For example, given a set of coupons { 1 2 4 −1 }, and a set of product values { 7 6 −2 −3 } (in Mars dollars M$) where a negative value corresponds to a bonus product. You can apply coupon 3 (with N being 4) to product 1 (with value M$7) to get M$28 back; coupon 2 to product 2 to get M$12 back; and coupon 4 to product 4 to get M$3 back. On the other hand, if you apply coupon 3 to product 4, you will have to pay M$12 to the shop.
Each coupon and each product may be selected at most once. Your task is to get as much money back as possible.!
译:火星的魔法商店正在提供一些魔法优惠券。 每张优惠券上印有一个整数N,这意味着当您将此优惠券与产品一起使用时,您可以获得该产品价值的N倍! 更重要的是,商店还免费提供一些奖励产品。 但是,如果您将带有正 N 的优惠券应用于此奖励产品,则您必须向商店支付奖励产品价值的 N 倍…但是,嘿,神奇的是,他们有一些带有负 N 的优惠券!
例如,给定一组优惠券 { 1 2 4 -1 } 和一组产品值 { 7 6 -2 -3 }(以火星美元 M$),其中负值对应于奖励产品。 您可以将优惠券3(N为4)应用到产品1(价值M$7),获得M$28返还; 产品 2 的优惠券 2 可返还 M$12; 和产品 4 的优惠券 4 可返还 M$3。 另一方面,如果您将优惠券 3 应用于产品 4,您将需要向商店支付 M$12。
每个优惠券和每个产品最多只能选择一次。 您的任务是尽可能多地收回资金。
Input Specification:
Each input file contains one test case. For each case, the first line contains the number of coupons NC, followed by a line with NC coupon integers. Then the next line contains the number of products NP, followed by a line with NP product values. Here 1≤NC,NP≤105, and it is guaranteed that all the numbers will not exceed 230.
译:每个输入文件包含一个测试,对于每个用例,第一行给出优惠券的数量 NC ,紧跟着一行是 NC 个优惠整数。接下来一行是商品的数量 NP ,紧跟着一行是 NP 个商品的价格。 1≤NC,NP≤105 , 并且保证所有的数字不会超过 230 。
output Specification :
For each test case, simply print in a line the maximum amount of money you can get back.
译:对于每个测试用例,简单的在一行中输出能够收回的最大数额的资金。
Sample Input :
4
1 2 4 -1
4
7 6 -2 -3
Sample Output :
43
The Idea:
首先是理解题目意思,在读懂题目之后,其实这一题的思路很简单,就是如何从两个数组中分别取一个数相乘,得到的结果最大(如果取出后乘积为负,可不取)。
- 理论支持(数学功底):正序和 > 乱序和 > 逆序和。
- 将两个数组中的元素按照从大到小排序,并且记录其中的正数个数。
- 正数部分分别相乘,负数部分分别相乘,得到结果即可。
The Codes:
#include<bits/stdc++.h>
using namespace std ;
const int maxn = 100010 ;
int con[maxn] , pro[maxn] ;
int nc , np ;
long long ans = 0 ;
int cnt1 = 0 , cnt2 = 0 ; // 记录优惠券和商品中的正数个数
bool cmp(int a , int b){
return a > b ;
}
int main(){
cin >> nc ;
for(int i = 0 ; i < nc ; i ++){
cin >> con[i] ;
if(con[i] > 0 ) cnt1 ++ ;
}
cin >> np ;
for(int i = 0 ; i < np ; i ++){
cin >> pro[i] ;
if(pro[i] > 0 ) cnt2 ++ ;
}
sort(con , con + nc , cmp ); // 按照从大到小排序
sort(pro , pro + nc , cmp ); // 按照从大到小排序
// len1为正数部分可以收回资金的优惠券数,len2 为负数部分可以收回资金的优惠券数
int len1 = min(cnt1 , cnt2) , len2 = min(nc - cnt1 , np - cnt2) ;
for(int i = 0 ; i < len1 ; i ++){
ans += (long long) (con[i] * pro[i]) ;
}
for(int i = 0 ; i < len2 ; i ++){
ans += (long long) (con[nc - i - 1] * pro[np - i - 1]) ;
}
cout << ans << endl ;
return 0 ;
}