Codeforces Round #608 (Div. 2) - D. Portals(贪心)

Posted zzzzzzy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #608 (Div. 2) - D. Portals(贪心)相关的知识,希望对你有一定的参考价值。

题意:你起初有一支军队,有$k$个士兵,现在有$n$座城堡,你若想占领第$i$座城堡,至少得有$a[i]$个士兵才能占领$($占领后士兵不会减少$)$,占领了第$i$座城堡后,你将得到$b[i]$个士兵,然后你有两种方式防御你占领的城堡:

  • 在你占领第$i$个城堡后留下一个士兵防御第$i$个城堡
  • 有$m$个传送门,能从$u_{i}$传送到$v_{i}(u_{i}>v_{i})$,你可以在占领完第$u_{i}$座城堡后再派一个士兵去防御第$v_{i}$个城堡

如果你防御了第$i$座城堡,你能得到$c[i]$的成就值,现在问你,如果你能占领全部的城堡,你能获得的最大的成就值是多少,若不能占领全部的城堡, 输出$-1$。

思路:对于每一座城堡,如果它能在多个地方被防御,那么肯定选择最远能够被防御的地方,所以预处理出$to[i][j]$表示第$to[i][j]$个城堡最远能被防御的地方是第$i$个城堡,根据贪心的思想,我们对于城堡$i$,应该将城堡$i$能够到达的城堡$to[i][j]$全部进行防御,防御时按照成就值从高到低依次防御,当没有士兵进行防御时,如果当前需要防御的城堡的成就值大于你已经防御的城堡里面成就值的最小值,则应该放弃那个成就值最小的城堡,来防御当前的城堡,当发现自己的士兵不够占领某个城堡时,贪心放弃那些成就低的城堡,利用优先队列,每次放弃城堡时取出队头即可。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <vector>
 
using namespace std;
 
const int N = 5010;
 
struct node {
    int a, b, c;
};
 
int n, m, k, pos[N];
vector<int> to[N];
node p[N];
priority_queue< int, vector<int>, greater<int> > q;
 
void init()
{
    for (int i = 1; i <= n; i++) pos[i] = i;
}
 
bool cmp(int a, int b)
{
    return p[a].c > p[b].c;
}
 
int main()
{
    scanf("%d%d%d", &n, &m, &k);
    init();
    for (int i = 1; i <= n; i++)
        scanf("%d%d%d", &p[i].a, &p[i].b, &p[i].c);
    for (int i = 1; i <= m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        pos[v] = max(pos[v], u);
    }
    for (int i = 1; i <= n; i++) to[pos[i]].push_back(i);
    for (int i = 1; i <= n; i++) sort(to[i].begin(), to[i].end(), cmp);
    int res = 0, flag = 1;
    for (int i = 1; i <= n; i++) {
        if (p[i].a > k) {
            int dis = p[i].a - k;
            if (dis > q.size()) {
                flag = 0; break;
            }
            while (dis--) {
                int tp = q.top(); q.pop();
                res -= tp, k++;
            }
        }
        k += p[i].b;
        for (int j = 0; j < (int)to[i].size(); j++) {
            int v = to[i][j];
            if (0 == p[v].c) continue;
            if (0 == k && !q.empty() && p[v].c > q.top()) {
                int tp = q.top(); q.pop();
                res -= tp, k++;
            }
            if (k > 0) res += p[v].c, q.push(p[v].c), k--;
        }
    }
    if (0 == flag) printf("-1
");
    else printf("%d
", res);
    return 0;
}

以上是关于Codeforces Round #608 (Div. 2) - D. Portals(贪心)的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #608 (Div. 2) - D. Portals(贪心)

Codeforces Round #336 (Div. 2) D. Zuma(区间DP)

Codeforces Round #436 E. Fire(背包dp+输出路径)

[ACM]Codeforces Round #534 (Div. 2)

CodeForces - 608B

Codeforces Round #726 (Div. 2) B. Bad Boy(贪心)