题目链接
题意:给两组数据,求累加两两相乘的和最大,注意数据中有负数。
分析:乍看题目没看懂,(流下了英语差的泪水.jpg),仔细读才理解题意,其实就是考贪心思想,我们按正数大于负数,绝对值大的排前面的思想对两组数据进行排序,最后用i,j分别进行遍历,求取出两数的乘积,乘积大于0则i++,j++,否则让其中的正数对应的下标++。
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
int nc,np,num;
typedef long long ll;
ll sum,mul;
struct Node{
ll v;
bool neg;
}node1[maxn],node2[maxn];
bool cmp(Node a, Node b){
if(a.neg != b.neg){
return a.neg<b.neg; //正数比负数大
}
return a.v>b.v; //符号相同则绝对值大
}
int main(){
cin>>nc;
for(int i = 0; i<nc; i++){
cin>>num;
if(num < 0) {
num = -num;
node1[i].neg = true;
}
node1[i].v = num;
}
cin>>np;
for(int i = 0; i<np; i++){
cin>>num;
if(num < 0) {
num = -num;
node2[i].neg = true;
}
node2[i].v = num;
}
sort(node1, node1+nc, cmp);
sort(node2, node2+np, cmp);
int i=0, j=0;
while(i<nc && j<np){ //采用贪心的思想, 先将node1和node2按正数大于负数
//绝对值大的排前面的方法排序,后遍历两两进行相乘,大于0则符合要求
ll na = node1[i].v;
if(na == 0) {
i++;
continue; //遇到0跳过
}
if(node1[i].neg) na = -na;
ll nb = node2[j].v;
if(nb == 0) {
j++; //遇到0跳过
continue;
}
if(node2[j].neg) nb = -nb;
mul = na*nb;
if(mul > 0){ //乘积大于0则i,j跳到下一个数继续
i++;
j++;
sum += mul;
}
else {
if(na > 0) i++; //否则让na和nb中那个大于0的数++
if(nb > 0) j++;
}
}
cout<<sum<<'\n';
return 0;
}