HDU 4864 Task

来源:互联网 发布:nba全明星赛数据 编辑:程序博客网 时间:2024/04/30 07:09

题目:

Description

Today the company has m tasks to complete. The ith task need xi minutes to complete. Meanwhile, this task has a difficulty level yi. The machine whose level below this task’s level yi cannot complete this task. If the company completes this task, they will get (500*xi+2*yi) dollars. 
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 input contains several test cases. 
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

For each test case, output two integers, the maximum number of the tasks which the company can complete today and the money they will get.
 

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;}

3 0
原创粉丝点击