騰訊2018秋招筆試真題——安排機器
阿新 • • 發佈:2019-01-02
題目描述:小Q的公司最近接到m個任務,第i個任務需要Xi的時間去完成,難度等級為yi。
小Q擁有n臺機器,每臺機器最長工作時間zi,機器等級wi。
對於一個任務,它只能交由一臺機器來完成,如果安排給它的機器的最長工作時間小於任務需要的時間,則不能完成,
如果完成這個任務將獲得200*xi + 3*yi收益。
對於一臺機器,它一天只能完成一個任務,如果它的機器等級小於安排給它的任務難度等級,則不能完成。
小Q想在今天儘可能的去完成任務,即完成的任務數量最大。如果有多種安排方案,小Q還想找到收益最大的那個方案。小Q需要你來幫助他計算一下。
輸入描述:輸入包括 N + M + 1行
輸入的第一行為兩個正整數n和m(1 <= n, m <= 100000),表示機器的數量和任務的數量。
接下來n行,每行兩個整數zi和wi(0 < zi < 1000, 0 <= wi <= 100),表示每臺機器的最大工作時間和機器等級。
接下來的m行,每行兩個整數xi和yi(0 < xi < 1000, 0 <= yi <= 100),表示每個任務需要的完成時間和任務的難度等級。
輸出描述:輸出兩個整數,分別表示最大能完成的任務數量和獲取的利益。
輸入: 1 2
100 3
100 2
100 1
小Q擁有n臺機器,每臺機器最長工作時間zi,機器等級wi。
對於一個任務,它只能交由一臺機器來完成,如果安排給它的機器的最長工作時間小於任務需要的時間,則不能完成,
如果完成這個任務將獲得200*xi + 3*yi收益。
對於一臺機器,它一天只能完成一個任務,如果它的機器等級小於安排給它的任務難度等級,則不能完成。
小Q想在今天儘可能的去完成任務,即完成的任務數量最大。如果有多種安排方案,小Q還想找到收益最大的那個方案。小Q需要你來幫助他計算一下。
輸入描述:輸入包括 N + M + 1行
輸入的第一行為兩個正整數n和m(1 <= n, m <= 100000),表示機器的數量和任務的數量。
接下來n行,每行兩個整數zi和wi(0 < zi < 1000, 0 <= wi <= 100),表示每臺機器的最大工作時間和機器等級。
接下來的m行,每行兩個整數xi和yi(0 < xi < 1000, 0 <= yi <= 100),表示每個任務需要的完成時間和任務的難度等級。
輸出描述:輸出兩個整數,分別表示最大能完成的任務數量和獲取的利益。
輸入: 1 2
100 3
100 2
100 1
輸出:1 20006
詳解:按照時間和等級降序,這樣保證取到的一定是收益最大的解(因為時間的收益嚴格大於等級,所以時間作為第一關鍵字,如果能完成收益大的任務,自然不會去完成收益低的任務);然後在此基礎上,加所有工作時間大於等於任務的機器加入multiset中,取出等級最接近任務等級的,且大於等於任務等級的,就是lower_bound,這樣可以保證完成的任務一定是最多的,不會遺漏。(因為任務和機器都按照時間進行過排序,那麼在set中機器的時間一定是可以完成後續任務的,它們是被時間更長的任務選擇進來的,所以在此不需要考慮機器的工作時間了,在後面他們的時間不會有區別都是一樣的,為了防止後面出現等級更大的任務,那麼肯定要選擇等級剛好大於任務的機器了),這樣兩次貪心下來得到的就是一定是最優解了,而且第二次貪心可以二分,不會超時。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
struct node
{
int x;
int y;
};
int cmp(node a, node b)
{
if (a.x == b.x)
return a.y > b.y;
return a.x > b.x;
}
int main()
{
int n, m;
int num = 0;
long long profit = 0;
vector<node > machine(n);
vector<node > job(m);
scanf("%d%d", &n, &m);
for (int i = 0; i < n; ++i)
{
scanf("%d%d", &machine[i].x, &machine[i].y);
}
for (int i = 0; i < m; ++i)
{
scanf("%d%d", &job[i].x, &job[i].y);
}
sort(machine.begin(), machine.end(), cmp);
sort(job.begin(), job.end(), cmp);
vector<int> cnt(105, 0);
for (int i = 0, j = 0; i < m; ++i)
{
while (j < n && machine[j].x >= job[i].x)
{
cnt[machine[j].y]++;
j++;
}
for (int k = job[i].y; k <= 100; ++k)
{
if (cnt[k])
{
++num;
cnt[k]--;
profit += 200 * job[i].x + 3 * job[i].y;
break;
}
}
}
cout << num << " " << profit << endl;
return 0;
}