D. Portals (思维+贪心 || dp)

传送门

题意: 你起初有一支军队,有 k 个士兵,现在,有 n 座城堡, 你若想占领第 i 座城堡,那你至少得有 ai 个士兵才能占领。

    占领了 第 i 座城堡, 你可以扩大兵力, 得到 bi 的士兵。  然后你有两种方式使得防御你占领的城堡:

    1、在你占领完的时候就留下一个士兵,防御它。

    2、有m条小道,从ui -> vi; ui > vi; 你可以在占领完第 ui 座城堡的时候再 派一个士兵去 vi 防御 vi。

    你必须防御了第 i 座城堡你才能得到  成就 ci。  现在问你, 在能占领 全部城堡的前提下, 最大的 成就是多少。

    若不能占领全部城堡, 输出 -1;

解: 首先, 显而易见的, 对于每座城堡, 若它能在多个地方被防御,那肯定是选最晚的那个时候再来考虑是否对这座城堡进行防御。

   不如, 若有一条小道 3 1; 那你肯定是在占领完第3座城堡的时候,再考虑是否对第1座城堡防御。

   然后就有两种做法:

        一、 dp

扫描二维码关注公众号,回复: 8569530 查看本文章

   5000座塔,最多5000个士兵。 5000 * 5000 的dp, 完全没问题。 

#include <bits/stdc++.h>
#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
using namespace std;

const int N = 5e3 + 5;

int dp[N], a[N], b[N], c[N], last[N];

vector<int> G[N];

int main() {
    int n, k, m;
    scanf("%d %d %d", &n, &m, &k);
    mem(dp, -1); dp[k] = 0;
    rep(i, 1, n) {
        scanf("%d %d %d", &a[i], &b[i], &c[i]);
        last[i] = i;
    }
    rep(i, 1, m) {
        int u, v; scanf("%d %d", &u, &v);
        last[v] = max(last[v], u);
    }
    rep(i, 1, n) {
        G[last[i]].pb(c[i]);
    }
    rep(i, 1, n) {
        rep(j, 0, a[i] - 1) dp[j] = -1;
        dep(j, b[i], 5000) dp[j] = dp[j - b[i]];
        for(auto v : G[i]) {
            rep(j, 0, 5000) {
                if(dp[j + 1] != -1) dp[j] = max(dp[j], dp[j + 1] + v);
            }
        }
    }
    int ans = -1;
    rep(i, 0, 5000) ans = max(ans, dp[i]);
    printf("%d\n", ans);
    return 0;
}
View Code

  二、反悔贪心

  对于每个城堡,我们都选择防御,然后,当出现士兵不够占领城堡的情况的时候,再贪心的把那些成就低的城堡放弃掉。

#include <bits/stdc++.h>
#define LL long long
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF INT_MAX
#define inf LLONG_MAX
using namespace std;

const int N = 5e3 + 5;

int a[N], b[N], c[N], last[N];

vector< int > G[N];

priority_queue<int, vector<int>, greater<int> > Q;

int main() {
    int n, m, k; scanf("%d %d %d", &n, &m, &k);
    rep(i, 1, n) {
        scanf("%d %d %d", &a[i], &b[i], &c[i]);
        last[i] = i;
    }
    rep(i, 1, m) {
        int u, v; scanf("%d %d", &u, &v);
        last[v] = max(last[v], u);
    }
    rep(i, 1, n) {
        G[last[i]].pb(c[i]);
    }
    int now = k;
    int res = 0;
    rep(i, 1, n + 1) {
        if(now < a[i]) {
            while(!Q.empty() && now < a[i]) {
                now++;  res -= Q.top(); Q.pop();
            }
            if(now < a[i]) {
                res = -1; break;
            }
        }
        now += b[i];
        for(auto v : G[i]) {
            now--, res += v;
            Q.push(v);
        }
    }
    printf("%d\n", res);
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/Willems/p/12187074.html