LA 4254 Processor (二分 + 贪心)

Posted Tartarus

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LA 4254 Processor (二分 + 贪心)相关的知识,希望对你有一定的参考价值。

二分没什么好说的,但 \\(check\\) 函数很难写

首先将所有任务按左端点排序,然后枚举时间,速度就是单位时间的工作量

在当前时间之前开始的所有任务中,贪心地先完成结束时间早的任务,使用优先队列来实现

(枚举任务查看时间的写法要处理浮点数,没有通过,不知道是哪里有问题)

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 10010;
const double eps = 1e-11;

int T, n; 

struct Task{
	int r, d, w;
	
	bool operator < (const Task &x) const{
		return d > x.d;
	}
}a[maxn]; 

int maxt, mint;
priority_queue<Task> q; 
bool check(int x){
	while(!q.empty()) q.pop();
	
	int pos = 1;
	for(int i = 1 ; i <= maxt ; ++i){
		if(q.empty()) {
			if(pos > n) return true;
			i = a[pos].r;
		}
		
		while(a[pos].r <= i && pos <= n){
			q.push(a[pos]);
			++pos;
		}
		
		int tmp = x;
		
		while(!q.empty() && tmp > 0){
			Task u = q.top(); q.pop();
			
			if(u.d <= i) return false;	
			
			if(u.w > tmp){
				u.w -= tmp;
				tmp = 0;
				q.push(u);
			} else{
				tmp -= u.w;
			}		
		}
	}
	
	return false;
}

bool cmp(Task x, Task y) { return x.r < y.r || (x.r == y.r && x.d < y.d) ; } 

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < \'0\' || ch > \'9\'){ if(ch == \'-\') f = -1; ch = getchar(); } while(ch >= \'0\' && ch <= \'9\'){ s = s * 10 + ch - \'0\'; ch = getchar(); } return s * f; }

int main(){
	scanf("%d", &T);
	while(T--){
		scanf("%d", &n);
		maxt = 0, mint = 1000000007;
				
		for(int i = 1 ; i <= n ; ++i){
			scanf("%d%d%d", &a[i].r, &a[i].d ,&a[i].w);
			maxt = max(maxt, a[i].d);
			mint = min(mint, a[i].r);
		}
		
		sort(a + 1, a + 1 + n, cmp);
		
		int ans = 0;
		
		int L = 0, R = 100000000;
		while(L <= R){
			int M = L + (R - L) / 2;
//			printf("%d\\n", M);
			if(check(M)){
				ans = M;
				R = M - 1;
			} else{
				L = M + 1;
			}
		}
		
		printf("%d\\n", ans);
	}
	return 0;
}

浮点数写法:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 10010;
const double eps = 1e-11;

int T, n; 

struct Task{
	int r, d, w;
	
	bool operator < (const Task &x) const{
		return d > x.d;
	}
}a[maxn]; 

bool check(int x){
	priority_queue<Task> q; 
	
	double t = 0;
	for(int i = 1 ; i <= n ; ){
		int lim = a[i].d;
		t = max((double)a[i].r, t);
		double left = 0;
		
		while(a[i].d <= lim && i <= n){
			q.push(a[i]);
			++i;
		}
		
		while(!q.empty()){
			Task u = q.top();
			
			if(t + eps < (double) u.r){
				left += (double) u.r - t;
				t = (double) u.r;
			}			
			
			if(q.size() == 1){
				left += u.d - t;
				if(left + eps < (double) u.w / x){
					return false;
				}

				t += left - ((double) u.w / x);
				
				q.pop();
				break;
			}
			
			if(t > u.d + eps) return false;
			if(u.d - t + eps < (double) u.w / x){
				return false;
			}
			t += (double) u.w / x;
			q.pop();
		}
	}
	
	return true;
}

bool cmp(Task x, Task y) { return x.r < y.r || (x.r == y.r && x.d < y.d) ; } 

ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < \'0\' || ch > \'9\'){ if(ch == \'-\') f = -1; ch = getchar(); } while(ch >= \'0\' && ch <= \'9\'){ s = s * 10 + ch - \'0\'; ch = getchar(); } return s * f; }

int main(){
	freopen("data.in", "r", stdin);
	freopen("ans.out", "w", stdout);
	scanf("%d", &T);
	while(T--){
		scanf("%d", &n);
				
		for(int i = 1 ; i <= n ; ++i){
			scanf("%d%d%d", &a[i].r, &a[i].d ,&a[i].w);
		}
		
		sort(a + 1, a + 1 + n, cmp);
		
		int ans = 0;
		
		int L = 0, R = 100000000;
		while(L <= R){
			int M = L + (R - L + 1) / 2;
			
			if(check(M)){
				ans = M;
				R = M - 1;
			} else{
				L = M + 1;
			}
		}
		
		printf("%d\\n", ans);
	}
	return 0;
}

以上是关于LA 4254 Processor (二分 + 贪心)的主要内容,如果未能解决你的问题,请参考以下文章

LA 4254 处理器(二分+贪心)

LA 4254 贪心

2019.9.22

一坨理论AC的题Orz sxy大佬

LA 3971 组装电脑(二分)

有序链表合并