欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

贪心_HDOJ4864_Task

程序员文章站 2024-03-13 23:08:52
...

点此打开题目页面

思路分析:

    根据对于用时为x, 级别为y的任务的酬劳为500 * x + y, 且y的最大值为100, 显然应该优先完成耗时长的任务, 考虑下面的贪心策略:

将所有任务以时间为第一关键字, 级别为第二关键字按照非递减排序得任务序列A[1...M], 依次考察A[1]...A[M], 对于每个任务, 选择可以完成该任务且级别最低的机器, 最终所有机器均被选择或A[1...M]均被考察后即得到可完成的最多任务数和可获得的最大酬劳, 通过证明每次选择后都存在一个包含当前选择的最优(完成任务数最多的同时获利最大)方案, 具体证明过程此处不再赘述, 下面给出AC代码:

//HDOJ4864_Task
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <functional>
#include <deque>
using namespace std;
const int MAX = 1e5 + 5;
pair<int, int> task[MAX];//first:执行时间, second:级别
deque<int> ma[101];//ma[i]级别为i的所有机器
int main(){
	int N, M; 
	while(cin >> N >> M){	
		for(int i = 0; i <= 100; ++i) ma[i].clear();//一定注意要清空ma[0...100]	
		for(int i = 1, s, t; i <= N; ++i) scanf("%d %d", &s, &t), ma[t].push_back(s);
		for(int i = 0; i <= 100; ++i) 
			if(!ma[i].empty()) sort(ma[i].begin(), ma[i].end(), greater<int>());
		for(int i = 1; i <= M; ++i) scanf("%d %d", &task[i].first, &task[i].second);
		sort(task + 1, task + M + 1, greater<pair<int, int> >());
		long long ans = 0, cnt = 0;
		for(int i = 1, j; i <= M; ++i){
			for(j = task[i].second; j <= 100 && (ma[j].empty() || ma[j].front() < task[i].first); ++j);
			if(j <= 100) ans += 500 * task[i].first + 2 * task[i].second, ++cnt, ma[j].pop_front();	
		}
		cout << cnt << " " << ans << endl;
	}
	return 0;
} 

 

 

相关标签: 贪心