NC20154 [JSOI2007]建築搶修(貪心)

題目鏈接

題意:
n有n個建築,每個建築有修復時間和截止時間
只有一個工人,假設路程不需要時間
最多可以讓多少個建築在截止時間前修復好
題解:
n<=15000n<=15000
感覺和那個老師教課問題很相似
想要教儘量多的課
只不過那個給的是起止時間,這個是需要時間和截止時間

貪心可以考慮幾種策略
1.1.按需要時間短的先做
2.2.按最晚開始時間(即截止時間減需要時間)的早晚來做
3.3.按截止時間早的先做

首先分析第一種,先做時間短的
時間短的但是其實他截止時間很晚
你做了這件事,反而耽誤了你一件截止時間早的事不能完成
所以這一種明顯不成立

然後分析第二種
如果一件事最晚開始時間很早,但是他花費時間很長
在這之間你完全可以做兩件比他開始時間晚的事
所以第二種也不成立

最後,說一下第三種
滿按截止時間早的先做,如果你當前時間如果滿足截止時間前做完
那麼就做這件事
但是如果這樣的話,會出現一個問題
這件事的持續時間很長,導致你本來能做後面兩件事的時間被這一件事佔用了
所以每次需要有一個反悔的機會,就是可以重新選擇
那麼這個反悔的機會就用一個堆維護,讓堆中放每件事的持續時間
top最大的時間在top,如果發現你這件事不能在截止時間前做完
那麼就去堆中找最大的時間,是否比它的持續時間要長
如果比它要長那麼就可以把堆中的那件事替換成這件事
由於是替換,結果是不變的,而且由於是按截止時間排序
那件事比他截止時間早,持續時間長都可以做完堆中的每一件
使你讓在做那件事的時候做現在新替換的事,仍然可以使這個堆成立
AC代碼

/*
    Author:zzugzx
    Lang:C++
    Blog:blog.csdn.net/qq_43756519
*/
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define endl '\n'
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
//const int mod=1e9+7;
const int mod=998244353;
const double eps = 1e-10;
const double pi=acos(-1.0);
const int maxn=1e6+10;
const ll inf=0x3f3f3f3f;
const int dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}};

struct node{
    ll s,t;
}p[maxn];
bool cmp(node a,node b){
    return a.t<b.t;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)cin>>p[i].s>>p[i].t;
    sort(p+1,p+1+n,cmp);
    priority_queue<int>q;
    ll sum=0,ans=0;
    for(int i=1;i<=n;i++){
        if(sum+p[i].s<=p[i].t){
            ans++;sum+=p[i].s;
            q.push(p[i].s);
        }
        else if(q.top()>p[i].s){
            sum-=q.top();q.pop();
            sum+=p[i].s;q.push(p[i].s);
        }
    }
    cout<<ans<<endl;
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章