[PAT解题报告] Magic Coupon

题目给了一个有趣的背景——在商店买东西,用不同优惠券可以把产品价值乘以一个不同系数。但是无论是系数,还是优惠券上的数都有正有负……火星上比较诡异。然后给定你产品和优惠券,问如何分配——每个产品只能用一个优惠券并且不能不用,每个优惠券只能用在一个产品上,也就是说最终要选n个产品和n个优惠券一对一搭配,让总价值和最大。

其实,这就是一个分配使得价值和最大的问题,我们知道对于a1,a2...an和b1 ,b 2 ...b n如果完全分配是“同序和”最大。即a 1<=a 2<=...<=a n并且b1 <=b 2 <= ...<=b n时对应乘积和最大。但是,我们不一定要全部使用,如果两个乘积是负数,我们没有必要在总和里加上它们。
于是我们可以把两个数组排序,如果最大的是正数,那么我们两个数组都从最大的正数开始分配,这样乘积才最大,总和也最大。
同理,如果最小的是负数,那么我们两个数组都从最小的负数(绝对值最大)开始分配,和正数分配是对称的。符号相反的两个数,乘积是负数,不要计算在总和就好了。

注意: 结果会超int。

代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>

using namespace std;

int a[100005],b[100005];

long long mul(long long x,long long y) {
    return x * y;
}

int main() {
int n, m;
    scanf("%d",&n);
    for (int i = 0; i < n; ++i) {
        scanf("%d",a + i);
    }
    scanf("%d",&m);
    for (int i = 0; i < m; ++i) {
        scanf("%d",b + i);
    }
    sort(a, a + n);
    sort(b, b + m);
    int froma = 0, fromb = 0;
    long long answer = 0;
    for (; (froma < n) && (fromb < m) && (a[froma] < 0) && (b[fromb] < 0); answer += mul(a[froma++], b[fromb++]))
    ;
    for (int i = n - 1, j = m - 1; (i >= froma) && (j >= fromb) && (a[i] > 0) && (b[j] > 0); answer += mul(a[i--], b[j--]))
    ;    
    printf("%lld\n",answer);
    return 0;
}

原题链接: http://www.patest.cn/contests/pat-a-practise/1037

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务