PAT (Advanced Level) Practice 1037 Magic Coupon (25 分) 凌宸1642

这是一道关于优化选择魔法优惠券以获取最高回馈的算法问题。给定一组优惠券和商品,每张优惠券有正负整数N,表示使用时可以获得或支付N倍商品价值。目标是最大化获得的回馈金额。算法思路是首先对优惠券和商品按数值大小进行排序,然后分别计算正数和负数部分的组合最大值。代码实现中通过排序和遍历计算了最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lingchen0522

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值