标签:bool code max portal names 贪心 自己 地方 while
题意:你起初有一支军队,有$k$个士兵,现在有$n$座城堡,你若想占领第$i$座城堡,至少得有$a[i]$个士兵才能占领$($占领后士兵不会减少$)$,占领了第$i$座城堡后,你将得到$b[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\n"); else printf("%d\n", res); return 0; }
Codeforces Round #608 (Div. 2) - D. Portals(贪心)
标签:bool code max portal names 贪心 自己 地方 while
原文地址:https://www.cnblogs.com/zzzzzzy/p/12197694.html