1. 程式人生 > >poj2970 The lazy programmer 【優先隊列】

poj2970 The lazy programmer 【優先隊列】

diff 分別是 put help other -a scan nbsp fine

A new web-design studio, called SMART (Simply Masters of ART), employs two people. The first one is a web-designer and an executive director at the same time. The second one is a programmer. The director is so a nimble guy that the studio has already got N contracts for web site development. Each contract has a deadline di

.

It is known that the programmer is lazy. Usually he does not work as fast as he could. Therefore, under normal conditions the programmer needs bi of time to perform the contract number i. Fortunately, the guy is very greedy for money. If the director pays him xi dollars extra, he needs only (biai

xi) of time to do his job. But this extra payment does not influent other contract. It means that each contract should be paid separately to be done faster. The programmer is so greedy that he can do his job almost instantly if the extra payment is (biai) dollars for the contract number i.

The director has a difficult problem to solve. He needs to organize programmer’s job and, may be, assign extra payments for some of the contracts so that all contracts are performed in time. Obviously he wishes to minimize the sum of extra payments. Help the director!

Input

The first line of the input contains the number of contracts N (1 ≤ N ≤ 100 000, integer). Each of the next N lines describes one contract and contains integer numbers ai, bi, di (1 ≤ ai, bi ≤ 10 000; 1 ≤ di ≤ 1 000 000 000) separated by spaces.

Output

The output needs to contain a single real number S in the only line of file. S is the minimum sum of money which the director needs to pay extra so that the programmer could perform all contracts in time. The number must have two digits after the decimal point.

Sample Input

2
20 50 100
10 100 50

Sample Output

5.00

題意:有n個合同,截止日期分別是di,有個程序員,完成每個合同的時間是bi。對於合同i,給他x元錢,相應完成時間變為bi-ai*x。求需要最少的錢數,保證該程序員按時完成所有合同。

算法:所有合同,按照截止日期排序。維護一個優先隊列,存儲歷史上完成的合同及相應使用時間。每下一個合同時間不夠用,就在歷史上選擇ai最大的合同,將其時間用錢來買,從而增加當前合同可以使用的時間。統計付錢總額。

代碼:

#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>

#define llint long long
#define LEN 100000

double ans;
int n;
int d[LEN], a[LEN], b[LEN], t[LEN];

struct pair2{
    int a,len;
    bool operator < (const pair2 &tmp) const{
        return a<tmp.a;
    }
}pairs[LEN];
std::priority_queue<pair2*> pq;

void input();
void work();
void output();

int main(){
    input();
    work();
    output();

    return 0;
}

void input(){
    scanf("%d", &n);
    for(int i=0;i<n;i++){
        scanf("%d %d %d", &a[i], &b[i], &d[i]);
        t[i]=i;
    }
}
bool compareSort(const int& i, const int& j){
    return d[i]<d[j];
}
void work(){
    int pair_i=0, cur=0;
    std::sort(t, t+n, compareSort);
    for(int i=0;i<n;i++){
        int &index = t[i];
        int remain=d[index]-cur;
        if(remain>=b[index]){
            pairs[pair_i].a = a[index];
            pairs[pair_i].len = b[index];
            pq.push(&pairs[pair_i++]);
            cur += b[index];
        }else{
            pairs[pair_i].a = a[index];
            pairs[pair_i].len = remain;

            remain = b[index]-remain;
            while(!pq.empty()){
                pair2* p = pq.top();
                if (remain <= p->len){
                    p->len -= remain;
                    ans += double(remain)/a[index];
                    if (!p->len) pq.pop();
                    remain = 0;
                    break;
                }else{
                    ans += double(p->len)/a[index];
                    pq.pop();
                    remain -= p->len;
                }
            }
            if (remain){
                ans += double(remain)/a[index];
            }

            pq.push(&pairs[pair_i++]);
            cur = d[index];
        }
    }
}
void output(){
    printf("%.2f\n", ans);
}

poj2970 The lazy programmer 【優先隊列】