CF1203F2 Complete the Projects (hard version) 反悔贪心

传送门

Complete the Projects (hard version)

题面翻译

CF1203F2 Complete the Projects (hard version) 反悔贪心_第1张图片

题目描述

The only difference between easy and hard versions is that you should complete all the projects in easy version but this is not necessary in hard version.

Polycarp is a very famous freelancer. His current rating is r r r units.

Some very rich customers asked him to complete some projects for their companies. To complete the i i i -th project, Polycarp needs to have at least a i a_i ai units of rating; after he completes this project, his rating will change by b i b_i bi (his rating will increase or decrease by b i b_i bi ) ( b i b_i bi can be positive or negative). Polycarp’s rating should not fall below zero because then people won’t trust such a low rated freelancer.

Polycarp can choose the order in which he completes projects. Furthermore, he can even skip some projects altogether.

To gain more experience (and money, of course) Polycarp wants to choose the subset of projects having maximum possible size and the order in which he will complete them, so he has enough rating before starting each project, and has non-negative rating after completing each project.

Your task is to calculate the maximum possible size of such subset of projects.

输入格式

The first line of the input contains two integers n n n and r r r ( 1 ≤ n ≤ 100 , 1 ≤ r ≤ 30000 1 \le n \le 100, 1 \le r \le 30000 1n100,1r30000 ) — the number of projects and the initial rating of Polycarp, respectively.

The next n n n lines contain projects, one per line. The i i i -th project is represented as a pair of integers a i a_i ai and b i b_i bi ( 1 ≤ a i ≤ 30000 1 \le a_i \le 30000 1ai30000 , − 300 ≤ b i ≤ 300 -300 \le b_i \le 300 300bi300 ) — the rating required to complete the i i i -th project and the rating change after the project completion.

输出格式

Print one integer — the size of the maximum possible subset (possibly, empty) of projects Polycarp can choose.

样例 #1

样例输入 #1

3 4
4 6
10 -2
8 -1

样例输出 #1

3

样例 #2

样例输入 #2

5 20
45 -6
34 -15
10 34
1 27
40 -45

样例输出 #2

5

样例 #3

样例输入 #3

3 2
300 -300
1 299
1 123

样例输出 #3

3

以上来自洛谷 以上来自洛谷 以上来自洛谷
建议先完成easy版

解题思路:

由题意可知,当 b i ≥ 0 b_i\ge0 bi0时该任务一定可以完成,故可将 b i ≥ 0 b_i\ge0 bi0的任务单独分出,以 a i a_i ai大小升序排列,依次顺序完成可完成的任务,当前rating值r满足 r < a i r < a_i r<ai时,说明自该任务后的 b i ≥ 0 b_i\ge0 bi0的任务都无法完成,跳出循环。即:

		if (y >= 0) {//bi>=0
			a1[++len1] = (Project) {
				x, y
			};
		}
inline bool cmp1(Project x, Project y) {
	return x.a < y.a;//以ai升序排列
}
	for (int i = 1; i <= len1; i++) {
		if (r >= a1[i].a) {
			r += a1[i].b;
			ans++;
		} else {//当前rating值r满足r
			break;
		}
	}

在分出 b i ≥ 0 b_i\ge0 bi0的任务同时,分出 b i < 0 b_i<0 bi<0的任务,并以 a i + b i a_i+b_i ai+bi大小降序排列(具体证明)。即:

inline bool cmp2(Project x, Project y) {
	return x.a + x.b > y.a + y.b;//以ai+bi降序排列
}

重点:

在此之后,我们可以使用优先队列来维护在当前任务之前所有已选任务中 b i b_i bi扣分最多的,在当无法继续进行下一任务时,判断去除此任务后当前任务是否能完成,即使用反悔贪心来解。核心部分:

	for (int i = 1; i <= len2; i++) {//核心
		if (r >= a2[i].a && r + a2[i].b >= 0) {
			r += a2[i].b, p_que.push(a2[i]);
			ans++;
		} else if (!p_que.empty() && p_que.top().b < a2[i].b) {
			r -= p_que.top().b;
			if (r >= a2[i].a) {
				r += a2[i].b, p_que.pop(), p_que.push(a2[i]);
			} else {
				r += p_que.top().b;
			}
		}
	}

AC Code:

// C++ includes used for precompiling -*- C++ -*-

// Copyright (C) 2003-2013 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a1 copy of the GNU General Public License and
// a1 copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// .

/** @file stdc++.h
 *  This is an implementation file for a1 precompiled header.
 */

// 17.4.1.2 Headers

// C
#ifndef _GLIBCXX_NO_ASSERT
	#include 
#endif
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#if __cplusplus >= 201103L
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
#endif

// C++
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#if __cplusplus >= 201103L
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
	#include 
#endif//=#include
using namespace std;
const int Maxn = 100 + 5;
int n, r, x, y;
int len1, len2;
struct Project {
	int a, b;
	inline bool operator < (const Project &a2) const {
		return b > a2.b;
	}
} a1[Maxn], a2[Maxn];
priority_queue<Project> p_que;
int ans;
inline bool cmp1(Project x, Project y) {
	return x.a < y.a;//以ai升序排列
}
inline bool cmp2(Project x, Project y) {
	return x.a + x.b > y.a + y.b;//以ai+bi降序排列
}
inline void work() {
	cin >> n >> r;
	for (int i = 1; i <= n; i++) {
		cin >> x >> y;
		if (y >= 0) {//即bi>=0
			a1[++len1] = (Project) {
				x, y
			};
		} else {//即bi<0
			a2[++len2] = (Project) {
				x, y
			};
		}
	}
	sort(a1 + 1, a1 + len1 + 1, cmp1);
	sort(a2 + 1, a2 + len2 + 1, cmp2);
	for (int i = 1; i <= len1; i++) {
		if (r >= a1[i].a) {
			r += a1[i].b;
			ans++;
		} else {//当前rating值r满足r
			break;
		}
	}
	for (int i = 1; i <= len2; i++) {//核心
		if (r >= a2[i].a && r + a2[i].b >= 0) {
			r += a2[i].b, p_que.push(a2[i]);
			ans++;
		} else if (!p_que.empty() && p_que.top().b < a2[i].b) {
			r -= p_que.top().b;
			if (r >= a2[i].a) {
				r += a2[i].b, p_que.pop(), p_que.push(a2[i]);
			} else {
				r += p_que.top().b;
			}
		}
	}
	cout << ans << endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	work();
	return 0;
}

你可能感兴趣的:(题解,c语言,算法,c++)