1037 Magic Coupon
Posted CSU迦叶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1037 Magic Coupon相关的知识,希望对你有一定的参考价值。
1. 贪心算法题,贪心策略:两组乘子相乘,每个数字至多用一次,希望得到最大的乘积。那么让A组绝对值最大的正数和B组最绝对值最大的正数相乘,次大的和次大的相乘……同样的让A组绝对值最大的负数和B组绝对值最大的负数相乘,次大的和次大的相乘,绝不发生正数和负数相乘的情况。0由于对结果没影响,不做考虑。
2.具体实施时,在读数据的时候就分别记下A组和B组各自的正数个数、负数个数,相乘时正数和负数分开,取A,B中较小的正数个数作为正数相乘的组数,取A,B中较小的负数个数作为负数相乘的组数。对两个数组进行从大到小排序。
3.这题比较碰巧的地方在于,由于从大到小排序,正数绝对值大到小是从前到后分布,负数绝对值大到小是从后往前分布,由于又知道各自的组数,因而遍历起来很清晰。
AC代码
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100010;
const int INF = 1000000000;//INF:下确界 SUP:上确界
const double eps = 1e-3;
bool cmp(int a,int b){
return a>b;
}
int main(){
int cobj[maxn],pobj[maxn];
int nc,np;//二者没有本质区别
scanf("%d",&nc);
int cobjMoreZero = 0;//数组cobj大于0的数字个数
int cobjLessZero = 0;//数组cobj小于0的数字个数
for(int i=0;i<nc;i++){
scanf("%d",&cobj[i]);
if(cobj[i]<0)cobjLessZero++;
if(cobj[i]>0)cobjMoreZero++;
}
scanf("%d",&np);
int pobjMoreZero = 0;
int pobjLessZero = 0;
for(int i=0;i<np;i++){
scanf("%d",&pobj[i]);
if(pobj[i]<0)pobjLessZero++;
if(pobj[i]>0)pobjMoreZero++;
}
//对两个数组进行从大到小排序
sort(cobj,cobj+nc,cmp);
sort(pobj,pobj+np,cmp);
long long res = 0;
for(int i=0;i<min(cobjMoreZero,pobjMoreZero);i++){
res += cobj[i]*pobj[i];
}
for(int i=0;i<min(cobjLessZero,cobjLessZero);i++){
res += cobj[nc-1-i]*pobj[np-1-i];
}
printf("%lld",res);
return 0;
}
以上是关于1037 Magic Coupon的主要内容,如果未能解决你的问题,请参考以下文章
PAT Advanced 1037 Magic Coupon (25) [贪?算法]
PAT (Advanced Level) 1037. Magic Coupon (25)