zoukankan      html  css  js  c++  java
  • Codeforces1203F2. Complete the Projects (hard version) (贪心+贪心+01背包)

    题目链接:传送门


    思路:

    对于对rating有提升的项目,肯定做越多越好,所以把$b_{i} >= 0$的项目按rating要求从小到大贪心地都做掉,得到最高的rating记为r。

    对于剩余的$b_{i} < 0$的项目,因为r的范围很小,在6e4的亚子,可以考虑用01背包来做。

    但是直接上01背包会WA,是因为不同项目选择的先后顺序会对结果有影响。

    比如现在的r是5,有两个项目,(ai,bi)分别为(3,-3)和(3,-1),如果先做前面的项目,就会导致rating不够做后一个项目。

    考虑任意两个项目i(ai,bi),j(aj,bj),先做i后做j的话,就要求初始的rating >= aj+|bi|,反之要求rating >= ai+b|j|。

    显然要求的初始rating越低越好:若aj+|bi| < ai+b|j|,说明前者要求更低,此时应先做i。移项一下就可以得ai-|bi| > aj-|bj|。

    所以ai-|bi|(bi<0)越大的项目,就可以越优先地做。根据这个sort一下,跑一遍01背包就出答案了。


    代码:O(r*n)

    #include <bits/stdc++.h>
    #define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
    #define N 105
    #define R 30005
    #define INF 0x3f3f3f3f
    #define mk(x) (1<<x) // be conscious if mask x exceeds int
    #define sz(x) ((int)x.size())
    #define mp(a,b) make_pair(a, b)
    #define endl '
    '
    #define lowbit(x) (x&-x)
    
    using namespace std;
    typedef long long ll;
    typedef double db;
    
    /** fast read **/
    template <typename T>
    inline void read(T &x) {
        x = 0; T fg = 1; char ch = getchar();
        while (!isdigit(ch)) {
            if (ch == '-') fg = -1;
            ch = getchar();
        }
        while (isdigit(ch)) x = x*10+ch-'0', ch = getchar();
        x = fg * x;
    }
    template <typename T, typename... Args>
    inline void read(T &x, Args &... args) { read(x), read(args...); }
    
    struct Node{
        int a, b;
        bool operator < (const Node& x) const {
            return a < x.a;
        }
    };
    int f[R<<1];
    vector <Node> vpos, vneg;
    bool cmp(Node x, Node y) {
        return x.a-x.b < y.a-y.b;
    }
    int main()
    {
        int n, r;
        read(n, r);
        for (int i = 1; i <= n; i++) {
            int a, b; read(a, b);
            if (b >= 0)
                vpos.push_back(Node{a, b});
            else
                vneg.push_back(Node{a, -b});
        }
        sort(vpos.begin(), vpos.end());
        sort(vneg.begin(), vneg.end(), cmp);
        int ans = 0;
        for (int i = 0; i < sz(vpos); i++) {
            Node tmp = vpos[i];
            if (r >= tmp.a) {
                r += tmp.b;
                ans++;
            }
        }
        for (int i = sz(vneg)-1; i >= 0; i--) {
            Node tmp = vneg[i];
            for (int j = max(tmp.a, tmp.b); j <= r; j++) {
                f[j-tmp.b] = max(f[j-tmp.b], f[j]+1);
            }
        }
        int res = 0;
        for (int i = 0; i <= r; i++)
            res = max(res, f[i]);
        ans += res;
        cout << ans << endl;
    
        return 0;
    }
    /*
    8 15000
    11031 -299
    8368 -289
    12459 -297
    6511 -297
    2628 -299
    3478 -296
    1050 -293
    12981 -294
    */
    View Code
  • 相关阅读:
    i++与++i
    acm语录
    c# SQL2000 access 远程连接操作
    C# 四舍五入函数
    WINDOWS 2003 远程桌面记录登陆IP
    jquery 资源
    php google baidu 分页
    Solutions to place plus or minus signs to a nonzero digits sequence 123456789 so that result of thus described arithmetic opera
    VB获取网页下文字的链接地址
    php cache 缓存方法类一
  • 原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/11657727.html
Copyright © 2011-2022 走看看