题目链接:戳我
题目大意:
有 M 个任务,每个任务有两个属性 x, y, x 代表完成这个任务需要多久时间, y代表这个任务的难度系数
有 N 个机器,每个机器同样也有两个属性 x ,y,x代表这个机器每天最长工作时间, y代表这个机器最高能完成的难度系数,且一天只能工作一次,即只能完成一个任务
如果完成了一个任务, 会获得 500 * x + 2 * y 元,x,y为对应任务的x和y
问 一天内 最多可以完成 多少任务, 完成这么多任务 所获得的最大利润
样例解释:
1 2 ----- 1 为 机器数 N, 2为任务数 M 接下来 先是 N行,每行两个代表机器属性,同理 下面M行
100 3
100 2
100 1
(100 3) 这个机器 完成 (100 2) 这个 1 任务 所获 利润 500*100+2* = 50004
解题思路:
如果选择 双重 for 循环去遍历,肯定是可以的,但是会超时,所以要优化,抛弃 for 循环的冗余部分,对于每个 任务,不用遍历所有的机器 去找到合适的。
取 机器 的游标 j,j表示所有机器中能完成该任务的下限机器,每次从当前 j 开始寻找最合适的 j。
首先 把 任务 和 机器 都按照 x 从大到小排序,x相同y从大到小排序, 排序之后从头到尾遍历每一个任务对于 每一个 任务, 选择 所有 合适 的机器 中 y 最小的那个,
巧妙的代码:
//Author LJH //www.cnblogs.com/tenlee #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #define clc(a, b) memset(a, b, sizeof(a)) using namespace std; const int inf = 0x3f; const int INF = 0x3f3f3f3f; const int maxn = 1e6+5; struct Task { int x, y; }task[maxn], mac[maxn]; int n, m; int ha[maxn]; bool cmp(Task A, Task B) { if(A.x == B.x) return A.y > B.y; return A.x > B.x; } int main() { while(~scanf("%d %d", &n, &m)) { for(int i = 0; i < n; i++) { scanf("%d %d", &mac[i].x, &mac[i].y); } for(int i = 0; i < m; i++) { scanf("%d %d", &task[i].x, &task[i].y); } sort(mac, mac+n, cmp); sort(task, task+m, cmp); memset(ha, 0, sizeof(ha)); int j = 0, k = 0, num = 0; long long ans = 0; for(int i = 0; i < m; i++) { while(j < n && (mac[j].x >= task[i].x)) // 找到 下限 的 机器 j { ha[mac[j].y]++; //把所有 x 合适的 机器的 y 记下来 j++; } for(k = task[i].y; k <= 100; k++) { if(ha[k]) //从 x 合适 的机器 中 挑选 y 也合适, 同时 y 最小 { ans += (500 * task[i].x + 2 * task[i].y); ha[k]--; //该机器已用,减去 num++; break; } } } printf("%d %lld ", num, ans); } return 0; }