CodeforcesF2. 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 ‘\n‘
#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
*/

原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/11657727.html

时间: 2024-10-10 10:51:11

CodeforcesF2. Complete the Projects (hard version) (贪心+贪心+01背包)的相关文章

Codeforces 1203F1 Complete the Projects (easy version)

cf题面 Time limit 2000 ms Memory limit 262144 kB 解题思路 看见这题觉得贪心可做,那就贪吧.(昨天真是贪心的一天,凌晨才被这两道贪心题虐,下午多校又来,感觉我现在比赛时候想贪心就是瞎猜,猜出一个结论就想办法hack,想不出hack就交上去,然后WA,然后自闭,很难摸到门道) 下面这些是我的做题和思考过程-- 显然要先把能加rating和不掉rating的做了,而且要按照要求从低到高的顺序做,因为如果当前rating能满足要求高的,那也能满足要求低的,如

Codeforces 1203F2 Complete the Projects (hard version)(dp)

啊,dp,万恶的dp. 本来不想补的,被某人押着说div3这么可以不ak于是不得不补了.真是痛苦的经历.(笑) 题目链接:https://codeforces.com/problemset/problem/1203/F2 题目大意:给定任务个数n和初始值r,完成每个任务需要有ai的r值,完成后r值会改变bi,问最多能完成多少任务(要保证最后r>=0) 思路:首先如果是正值的话自然按照a从小到大排一遍能加的都加上,然后问题在于负值.贪心显然不行,或者说这其实就是个背包问题的轻度转换,首先要做的预处

Codeforces 1203F2 Complete the Projects (hard version)

[cf题面](https://codeforces.com/contest/1203/problem/F2 Time limit 2000 ms Memory limit 262144 kB 解题思路 先留坑,吃完饭来填 源代码 #include<cstdio> #include<algorithm> int n,r; struct Data{ int need,delta; bool operator < (const Data & a)const{ if(delt

0-1背包的动态规划算法,部分背包的贪心算法和DP算法------算法导论

一.问题描述 0-1背包问题,部分背包问题.分别实现0-1背包的DP算法,部分背包的贪心算法和DP算法. 二.算法原理 (1)0-1背包的DP算法 0-1背包问题:有n件物品和一个容量为W的背包.第i件物品的重量是w[i],价值是v[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大.其中每种物品只有一件,可以选择放或者不放. 最优子结构性质:对于0-1问题,考虑重量至多W的最值钱的一包东西.如果去掉其中一个物品j,余下的必是除j以外的n-1件物品中,可以带走的重量

饭卡(01背包+贪心)

电子科大本部食堂的饭卡有一种很诡异的设计,即在购买之前判断余额.如果购买一个商品之前,卡上的剩余金额大于或等于5元,就一定可以购买成功(即使购买后卡上余额为负),否则无法购买(即使金额足够).所以大家都希望尽量使卡上的余额最少. 某天,食堂中有n种菜出售,每种菜可购买一次.已知每种菜的价格以及卡上的余额,问最少可使卡上的余额为多少. Input多组数据.对于每组数据: 第一行为正整数n,表示菜的数量.n<=1000. 第二行包括n个正整数,表示每种菜的价格.价格不超过50. 第三行包括一个正整数

HDU -2546饭卡(01背包+贪心)

这道题有个小小的坎,就是低于5块不能选,大于5块,可以任意选,所以就在初始条件判断一下剩余钱数,然后如果大于5的话,这时候就要用到贪心的思想,只要大于等于5,先找最大的那个,然后剩下的再去用背包去选择,这样的结果一定是最优的.因为最大的那个一定会被选中,剩下多少钱都无所谓,用背包可以获得剩下的最优解,所以最后也是最优解 代码如下 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using

[2012山东ACM省赛] Pick apples (贪心,全然背包,枚举)

Pick apples Time Limit: 1000MS Memory limit: 165536K 题目描写叙述 Once ago, there is a mystery yard which only produces three kinds of apples. The number of each kind is infinite. A girl carrying a big bag comes into the yard. She is so surprised because s

TopCoder SRM502 Div1 500 贪心 01背包

原文链接https://www.cnblogs.com/zhouzhendong/p/SRM502-500.html SRM502 Div1 500 好题. 首先,如果已经确定了解决所有问题的优先级,只需要对于每一个问题是否被解决做出决策,那么显然直接 01 背包就好了. 事实上,我们是可以贪心地确定两个问题的优先程度的. 对于两个问题,假设分别为 a 和 b,则先做 a 再紧接着做 b 和先做 b 再紧接着做 a 的收益之差为 \[ \begin{eqnarray*} &&(-dec_a

Codeforces Round #602 (Div. 2, based on Technocup 2020 Elimination Round 3) D2. Optimal Subsequences (Hard Version) 数据结构 贪心

D2. Optimal Subsequences (Hard Version) This is the harder version of the problem. In this version, 1≤n,m≤2?105. You can hack this problem if you locked it. But you can hack the previous problem only if you locked both problems. You are given a seque