Codeforces 854

来源:互联网 发布:软件订阅模式 编辑:程序博客网 时间:2024/06/05 14:58

题意:对于给定的N个飞机降落时刻。现在需要延迟K分钟。需要重新安排飞机降落时刻。唯一的限制是新的降落时刻表中,每架飞机的降落时刻不能早于原来的时刻。同时,每架飞机有一个延迟费用,每于原来的起降时刻有一分钟的差值则需要支付一定的延误费用Ci

思路:对于每架飞机的延误费用Ci,和新时刻表起飞的时间Ti,总花费有这样的公式:

SUM=i=1nCi(Tii)

转化后可得:

SUM=i=1nCiTii=1nCii

可知,后部分等式,为定值,要使得结果最小,需要使得前半部分值最小。

设对于i,j两架飞机消耗的总花费

Ci(Tii)+Cj(Tjj)

如果交换i,j的新起降时间可得:

Ci(Tji)+Cj(Tij)

设交换后总花费大于原费用可得:

Ci(Tii)+Cj(Tjj)<Ci(Tji)+Cj(Tij)

化简可得:
Ci<Cj

可得贪心策略:
在满足要求的情况下(Ti>i),取当前合法解中Ci最大的。

#include <bits/stdc++.h>using namespace std;using namespace std;typedef long long ll;typedef pair<int, int> pii;struct node{    ll p, c;    node(ll a = 0, ll b = 0)    {        p = a;        c = b;    }};struct cmp{    bool operator()(node x, node y)    {        if (x.c != y.c)return x.c > y.c;        return x.p < y.p;    }};set<node, cmp>s;int a[300000 + 50];int main(){    ll k;    int n;    scanf("%d%I64d", &n, &k);    ll ans = 0;    for (int i = 1; i <= n; i++)    {        ll c;        scanf("%I64d", &c);        s.insert(node(i, c));        if (i >= k + 1)        {            a[s.begin()->p] = i;            ans += s.begin()->c*(i - s.begin()->p);            s.erase(s.begin());        }    }    for (int i = 1; i <= k; i++)    {        a[s.begin()->p] = i + n;        ans += s.begin()->c*(i + n - s.begin()->p);        s.erase(s.begin());    }    printf("%I64d\n", ans);    //printf("%I64d\n", ans);    for (int i = 1; i <= n; i++)    {        if (i != 1)printf(" ");        printf("%d", a[i]);    }    printf("\n");    //sp;}
原创粉丝点击