UVALive 4850 Installations 贪心

题目链接 

题意

工程师要安装n个服务,其中服务Ji需要si单位的安装时间,截止时间为di。超时会有惩罚值,若实际完成时间为ci,则惩罚值为max{0,ci-di}。从0时刻开始执行任务,问惩罚值最大的两个服务的惩罚值之和的最小是多少?

 

分析

乍一看似乎要二分,但实际上并不是。贪心来做,按di从小到大安排任务,当di相等时,让完成时间短的排前,这样安排任务一定时更优的,但是并不能满足题目的要求。于是需要从两个最大惩罚值的前面挑选一个任务,并将它放置在后面,然后更新答案即可。

 

 

#include<cstdio>  
#include<algorithm>  
using namespace std;  
#define maxn 510  
struct Task{  
    int s, d;  
    bool operator <(const Task t) const{  
        if(t.d == d)  
            return s < t.s;  
        else  
            return d < t.d;    
    }  
}T[maxn];  
int pos, n;  
  
int solve(int cur) {  
    int MAX1 = 0, MAX2 = 0, sum = 0;  
    for(int i = 0; i <= pos; i++) {  
        if(i == cur)  
            continue;     
        sum += T[i].s;  
        if(sum - T[i].d >= MAX2)   
            MAX2 = sum - T[i].d;  
        if(MAX2 > MAX1)  
            swap(MAX1,MAX2);  
    }  
  
    sum += T[cur].s;  
    if(sum - T[cur].d >= MAX2)  
        MAX2 = sum - T[cur].d;  
    if(MAX2 > MAX1)  
        swap(MAX1,MAX2);  
  
    for(int i = pos + 1; i < n; i++) {  
        sum += T[i].s;  
        if(sum - T[i].d >= MAX2)  
            MAX2 = sum - T[i].d;  
        if(MAX2 > MAX1)  
            swap(MAX1,MAX2);  
    }  
    return MAX2 + MAX1;  
}  
  
int main() {  
    int test;  
    scanf("%d",&test);  
    while(test--) {  
        scanf("%d",&n);  
        for(int i = 0; i < n; i++)  
            scanf("%d%d",&T[i].s, &T[i].d);  
        sort(T,T+n);  
  
        int cur = 0, MAX1 = 0, MAX2 = 0, t = 0;  
        for(int i = 0; i < n; i++) {  
            cur += T[i].s;  
            if(cur - T[i].d >= MAX2) {  
                MAX2 = cur - T[i].d;  
                pos = i;      
            }  
            if(MAX2 > MAX1)  
                swap(MAX1,MAX2);  
        }  
  
        int ans = MAX1 + MAX2;  
        for(int i = 0; i < pos; i++)  
            ans = min(ans,solve(i));  
        printf("%d\n",ans);  
    }  
    return 0;  
}  

 

posted @ 2018-04-23 01:42  litos  阅读(210)  评论(0编辑  收藏  举报