質問
给出两个集合,各选出n个元素,求乘积最大值、
1037 魔法クーポン (25 分)
火星の魔法店ではいくつかの魔法クーポンを提供しています。各クーポンには整数 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 が戻ってきます。一方、商品 4 にクーポン 3 を適用すると、ショップに M$12 を支払う必要があります。
各クーポンおよび各商品は最大 1 回選択できます。あなたの仕事は、できるだけ多くのお金を取り戻すことです。
入力仕様:
各入力ファイルには 1 つのテスト ケースが含まれます。それぞれの場合、最初の行にはクーポンの数 N
Cが含まれ、その後に N Cクーポンの
整数
が続く行が続きます。次に、次の行には製品の数 N Pが含まれ、その後に N P製品の値が続く行が続きます。 ここで 1≤N C , N P ≤ 10 5であり、すべての数値が 2 30を超えないことが保証されます。
出力仕様:
各テスト ケースについて、返される最大金額を 1 行に出力するだけです。
入力例:
4
1 2 4 -1
4
7 6 -2 -3
末尾に空白行なし 出力
例:
43
一連の考え
2 つのセットの正の数と負の数を分離し、正の数を大きい順に並べ替え、負の数を小さい順に並べ替えます。対応する位置を乗算して最大値を取得します。
コード
#include<bits/stdc++.h>
using namespace std;
vector<int> set1_pos,set2_pos,set1_neg,set2_neg;
bool cmp(int a,int b){
return a>b;
}
int main(){
int n1,n2,temp;
cin>>n1;
for (int i = 0; i < n1; ++i) {
cin>>temp;
if(temp>=0){
set1_pos.push_back(temp);
} else{
set1_neg.push_back(temp);
}
}
cin>>n2;
for (int j = 0; j < n2; ++j) {
cin>>temp;
if(temp>=0){
set2_pos.push_back(temp);
} else{
set2_neg.push_back(temp);
}
}
int len1 = min(set1_pos.size(),set2_pos.size());
int len2 = min(set1_neg.size(),set2_neg.size());
sort(set1_pos.begin(),set1_pos.end(),cmp);
sort(set2_pos.begin(),set2_pos.end(),cmp);
sort(set1_neg.begin(),set1_neg.end());
sort(set2_neg.begin(),set2_neg.end());
int ans = 0;
for (int k = 0; k < len1; ++k) {
ans = ans + set1_pos[k]*set2_pos[k];
}
for (int l = 0; l < len2; ++l) {
ans = ans + set1_neg[l]*set2_neg[l];
}
cout<<ans;
return 0;
}
要約する
この問題は制限時間が広く、ソート機能が4回も使われています。