HDU 4864 Task
来源:互联网 发布:nba全明星赛数据 编辑:程序博客网 时间:2024/04/30 07:09
题目:
Description
The company has n machines. Each machine has a maximum working time and a level. If the time for the task is more than the maximum working time of the machine, the machine can not complete this task. Each machine can only complete a task one day. Each task can only be completed by one machine.
The company hopes to maximize the number of the tasks which they can complete today. If there are multiple solutions, they hopes to make the money maximum.
Input
The first line contains two integers N and M. N is the number of the machines.M is the number of tasks(1 < =N <= 100000,1<=M<=100000).
The following N lines each contains two integers xi(0<xi<1440),yi(0=<yi<=100).xi is the maximum time the machine can work.yi is the level of the machine.
The following M lines each contains two integers xi(0<xi<1440),yi(0=<yi<=100).xi is the time we need to complete the task.yi is the level of the task.
Output
Sample Input
1 2100 3100 2100 1
Sample Output
1 50004
有个类似的题目:点击打开我的博客
我的想法是把n个机器和m个作业task都按照降序排列,但是,
机器以y为第一关键字降序排列,以x为第一关键字降序排列,
作业以x为第一关键字降序排列,以y为第二关键字降序排列,即按照500*x+2*y排序
贪心策略是:
把作业从大到小安排机器,如果安排不了就不安排。
对于每个作业,选择不小于这个作业的最小机器。(什么叫最小机器,就是直接按照上面的排序来给出)
代码:
#include<iostream>#include<string.h>#include<algorithm>using namespace std;struct node{int x;int y;};node noden[100005];node nodem[100005];int list[100005];//list不为0表示对应的机器已经被选择int section[101];//section[i]是满足y不小于i的机器一共有多少个(对应最大下标)bool cmpy(node a, node b)//机器以y为第一关键字降序排列,以x为第一关键字降序排列{if (a.y > b.y)return true;if (a.y < b.y)return false;return a.x>b.x;}bool cmpx(node a, node b)//Task以x为第一关键字降序排列,以y为第二关键字降序排列{if (a.x > b.x)return true;if (a.x < b.x)return false;return a.y>b.y;}int main(){int n, m;while (cin >> n >> m){for (int i = 0; i < n; i++)cin >> noden[i].x >> noden[i].y;for (int i = 0; i < m; i++)cin >> nodem[i].x >> nodem[i].y;sort(noden, noden + n, cmpy);//机器sort(nodem, nodem + m, cmpx);//Taskmemset(list, 0, sizeof(list));memset(section, 0, sizeof(section));for (int i = 0; i < n; i++)section[noden[i].y] = i + 1;for (int i = 99; i >= 0; i--)if (section[i] < section[i + 1])section[i] = section[i + 1];long long num = 0, sum = 0, t;for (int i = 0; i < m; i++){t = nodem[i].y;for (int j = section[t] - 1; j >= 0; j--){if (list[j] || noden[j].x < nodem[i].x)continue;list[j] = 1;num++;sum += nodem[i].x * 500 + t * 2;break;}}cout << num << " " << sum << endl;}return 0;}
这个代码AC了,但是1326ms不够快。
下面,我开始阐述这个问题的本质,然后优化算法。
首先,作业毋庸置疑必须要这么排序,即优先选择500*x+2*y最大的作业。
这也就是说,不管所给数据是什么样的,只要优先给500*x+2*y大的作业安排合适的机器,就一定会得到最优解。
然后就只剩下一个问题了,对于一个作业来说,如何选择最合适的机器呢?
贪心策略无非就是,如果该作业是候选机器集不止一个元素,尽量选择某个元素,使得接下来待安排的作业不受影响。这样安排了的作业的数量就会最多。
所以说,问题可以抽离出这样一个小模型:
有2个作业和2个机器,作业A可以选择机器1和机器2,作业B只能选择机器1。
但是由于A优先安排机器,我们需要一个策略,能够准确而高效的判断,到底哪个机器是机器1,哪个机器是机器2?
请注意,在给作业A安排机器的时候,我们没有关于B的详细信息,所以这个时候还不知道作业B只能选择机器1。
模型的求解:
既然A可以选择机器2,而B不能,说明是因为B的y大于机器2的y(很显然B的x不超过A的x,A的x不超过机器2的x)
所以我们得到,机器1的y大于等于B的y,B的y大于机器2的y,即机器2的y小于机器1的y
(可能你觉得我这里又用到了作业B只能选择机器1这个条件,但是实际上我只是叙述的不够详细而已。
仔细辨别的话可以发现,我的求解没有问题。至少,对于这个独立的模型,很明显我的结论是对的)
模型的答案:
给A安排机器的时候,选择y较小的那个。
回到本题。
贪心策略其实很简单,不需要像上面那样。
给每个作业安排机器的时候,选择y最小的机器,如果不止一个,任选一个即可。
可能你已经发现,在上面的模型中,有的地方我写的是大于,有的地方我写的是大于等于。
我有自信,上面的模型不仅没有问题,而且很精准。
也就是说,仔细体会上面的模型,你就能明白,为什么如果y最小的机器不止一个,任选一个即可。
代码:
#include<iostream>#include<vector>#include<algorithm>using namespace std;struct node{int x;int y;};node noden[100005];node nodem[100005];vector<int>v[101];bool cmp(node a, node b)//Task以x为第一关键字降序排列,以y为第二关键字降序排列{if (a.x > b.x)return true;if (a.x < b.x)return false;return a.y>b.y;}int main(){ios_base::sync_with_stdio(false);int n, m;vector< int >::iterator p;while (cin >> n >> m){for (int i = 0; i <= 100; i++)v[i].clear();for (int i = 0; i < n; i++){cin >> noden[i].x >> noden[i].y;v[noden[i].y].insert(v[noden[i].y].end(), i);}for (int i = 0; i < m; i++)cin >> nodem[i].x >> nodem[i].y;sort(nodem, nodem + m, cmp);//Tasklong long num = 0, sum = 0;for (int i = 0; i < m; i++){bool b = false;for (int j = nodem[i].y; j <= 100; j++){if (b)break;for (p = v[j].begin(); p != v[j].end(); p++){if (noden[*p].x >= nodem[i].x){num++;sum += nodem[i].x * 500 + nodem[i].y * 2;v[j].erase(p);b = true;break;}}}}cout << num << " " << sum << endl;}return 0;}
- hdu 4864 Task 贪心
- hdu 4864 Task 贪心
- HDU 4864(Task)
- HDU 4864 Task
- HDU 4864 Task(贪心)
- HDU 4864 Task(贪心)
- hdu-4864-Task
- 【HDU 4864】Task【贪心】
- Hdu-4864-Task
- HDU 4864 Task
- HDU 4864 Task 贪心
- HDU 4864 Task 贪心
- hdu 4864 Task
- hdu 4864 Task(贪心)
- HDU 4864 Task (贪心)
- HDU 4864 Task
- HDU 4864----Task
- HDU 4864 Task
- Spring4笔记----工厂方法配置bean
- C# Matlab 相互调用
- Git 进阶 —— 远程仓库
- 1091. Acute Stroke (30)
- java语言基础入门——字符串两种建立方式的比较
- HDU 4864 Task
- Faster R-CNN系列之PYTHON篇
- 基本数据类型的包装类
- 不带表头的单向链表,带表头的单向链表,带表头的单向循环链表,带表头的双向循环链表。
- OSG帮助文档生成
- FreeMark 学习笔记
- TCP/IP协议(2)——数据链路层
- java.lang.NoClassDefFoundError: com/sun/mail/util/LineInputStream问题的解决
- leetcode No53. Maximum Subarray