zoukankan      html  css  js  c++  java
  • 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

       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
    ", 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
    ", res);
        return 0;
    }
    View Code
    一步一步,永不停息
  • 相关阅读:
    python __init__.py
    估算小结
    ssh vim中不小心按下ctrl+s
    估算方法
    SSH 下使vim语法高亮显示 && 终端下vim配置
    not enough arguments for format string搞死人
    函数的形参 实参
    Linux 共享内存机制
    select函数参数及其使用
    找出两个字符串最长公共子串
  • 原文地址:https://www.cnblogs.com/Willems/p/12187074.html
Copyright © 2011-2022 走看看