今天某公司有M個任務需要完成。
每個任務都有相應的難度級別和完成任務所需時間。
第i個任務的難度級別爲yi,完成任務所需時間爲xi分鐘。
如果公司完成此任務,他們將獲得(500 * xi + 2 * yi)美元收入。
該公司有N臺機器,每臺機器都有最長工作時間和級別。
如果任務所需時間超過機器的最長工作時間,則機器無法完成此任務。
如果任務難度級別超過機器的級別,則機器無法完成次任務。
每臺機器一天內只能完成一項任務。
每個任務只能由一臺機器完成。
請爲他們設計一個任務分配方案,使得該公司能夠最大化他們今天可以完成的任務數量。
如果有多種解決方案,他們希望選取賺取利潤最高的那種。
輸入格式
輸入包含幾個測試用例。
對於每個測試用例,第一行包含兩個整數N和M,分別代表機器數量和任務數量。
接下來N行,每行包含兩個整數xi,yi,分別代表機器最長工作時間和機器級別。
再接下來M行,每行包含兩個整數xi,yi,分別代表完成任務所需時間和任務難度級別。
輸出格式
對於每個測試用例,輸出兩個整數,代表公司今天可以完成的最大任務數以及他們將獲得的收入。
數據範圍
1≤N,M≤100000 ,
0<xi<1440,
0≤yi≤100
輸入樣例:
1 2
100 3
100 2
100 1
輸出樣例:
1 50004
思路:
剛開始看到這道題,覺得這是一個貪心,然後兩個數字一組,很自然考慮到用pair去寫,
那麼問題,怎麼貪?
通過要求的最大收入的表達是來看,x,y兩個數,500*x + 2 y;看數據範圍,y < 100; 2 * y < 200;
這個比500x 要小,因此我們根據x來貪。
先輸入,再根據時間從小到大排序;然後倒着做(貪心這麼貪),把任務放在循環裏,因爲任務要做,機器可以有不用的,一個機器一天完成一個,先做任務時間長的,然後把這個>=這個時間的機器找出來,所有的都要找出來,然後再根據任務難度選擇最合適的機器,然後任務數++,花費+=;同時把這個機器刪除。
這個題輸出的時候,犯了一個很低級的錯誤,我把輸出放到循環裏面了,最後給了我三個輸出。額呃呃呃來表達一下我的心情
代碼
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
using namespace std;
const int maxn = 1e5 + 10;
typedef pair<int,int> PII;
PII a[maxn],b[maxn];
int N,M,x,y;
multiset<int> s;
int main()
{
//機器數量和任務數量和任務數量
while(scanf("%d%d",&N,&M)!=EOF)
{
for(int i = 1; i <= N; i++)
//機器最長的工作時間和機器級別
scanf("%d%d",&a[i].first,&a[i].second);
for(int j = 1; j <= M; j++)
//完成任務所需要的時間和難度
scanf("%d%d",&b[j].first,&b[j].second);
//排序,從小到大
sort(a+1,a+N+1);
sort(b+1,b+M+1);
s.clear();
//任務數量
int cnt = 0;
//收入
long long ans = 0;
//把所有的任務按照時間排列,i表示任務,j表示機器
for(int i = M,j = N;i>=1; i--)
{
//任務的時間要比機器的時間短,即<=;還要考慮難度,因此把所有的都找出來,這時候找的是機器
while(j >= 1 && b[i].first <= a[j].first)
s.insert(a[j--].second);
//先把大的數字放進去,set是從小到大排的,lower_bound找到的是第一個大於等於b[i].second的,
auto it = s.lower_bound(b[i].second);
if(it != s.end()){
cnt++;
ans += 500*b[i].first + 2 * b[i].second;
//刪除,找到it,刪除這個機器,剩下的放在裏面
s.erase(it);
}
}
printf("%d %lld",cnt,ans);
}
return 0;
}
補充:pair默認的兩個first,second;
multiset允許重複,具有自動排序
遍歷
set元素唯一,默認升序
遍歷:
set<int> s;
for(auto it : s)
cout << it;