腾讯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 
#include 
#include 
#include 
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 machine(n);
    vector 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 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;
}

你可能感兴趣的:(C++)