卧薪尝胆,厚积薄发。
JSOI2007 建筑抢修
Date: Thu Aug 02 08:39:50 CST 2018 In Category: NoCategory

Description:

$n$ 项事务,每件事物有时长和截止日期,问最多能办几件事。
$1\le n \le 150000$

Solution:

发现无论按什么排序按顺序选择,都不一定是最优解。
于是换个思路,把所有事务按截止日期排序,一个一个选,并记录全部所用时间 $s$ ,如果 $s+a_i\le t_i$ ,那就做这件事,如果做不了,就在之前选一个最大的 $a_j(a_j>a_i)$ ,不做 $j$ 而做 $i$ ,并更新 $s$ 为 $s+a_i-a_j$ 。
这样做能尽量为后面的留下时间,还能保证尽量多。
如果有 $a_j > a_i$ 可以直接替换,因为把 $i$ 在原来 $j$ 的时间完成一定能符合要求,因为之前都是符合要求的,而截止日期又是排好序的。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
int n;
#define MAXN 150010
struct building
{
int a,t;
}b[MAXN];
bool cmp(building x,building y){return x.t < y.t;}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;++i)scanf("%d%d",&b[i].a,&b[i].t);
sort(b + 1,b + 1 + n,cmp);
priority_queue<int> q;
int sum = 0,ans = 0;
for(int i = 1;i <= n;++i)
{
if(sum + b[i].a <= b[i].t)
{
++ans;
sum += b[i].a;
q.push(b[i].a);
}
else
{
if(q.empty() || b[i].a > q.top())continue;
else
{
sum = sum - q.top() + b[i].a;
q.pop();q.push(b[i].a);
}
}
}
cout << ans << endl;
return 0;
}
In tag: 算法-贪心
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡