1. 程式人生 > >騰訊2018秋招筆試真題——安排機器

騰訊2018秋招筆試真題——安排機器

題目描述:小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

           輸出: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;
}