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

文章讨论了自由职业者Polycarp如何在满足评级要求的同时最大化完成项目数量,通过区分正负评级任务并采用贪心方法结合优先级队列来确定最优项目选择策略。
摘要由CSDN通过智能技术生成

传送门

Complete the Projects (hard version)

题面翻译

题目描述

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<ai时,跳出
			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
// <Licenses - GNU Project - Free Software Foundation>.

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

// 17.4.1.2 Headers

// C
#ifndef _GLIBCXX_NO_ASSERT
	#include <cassert>
#endif
#include <cctype>
#include <cerrno>
#include <cfloat>
#include <ciso646>
#include <climits>
#include <clocale>
#include <cmath>
#include <csetjmp>
#include <csignal>
#include <cstdarg>
#include <cstddef>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>

#if __cplusplus >= 201103L
	#include <ccomplex>
	#include <cfenv>
	#include <cinttypes>
	#include <cstdalign>
	#include <cstdbool>
	#include <cstdint>
	#include <ctgmath>
	#include <cwchar>
	#include <cwctype>
#endif

// C++
#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>

#if __cplusplus >= 201103L
	#include <array>
	#include <atomic>
	#include <chrono>
	#include <condition_variable>
	#include <forward_list>
	#include <future>
	#include <initializer_list>
	#include <mutex>
	#include <random>
	#include <ratio>
	#include <regex>
	#include <scoped_allocator>
	#include <system_error>
	#include <thread>
	#include <tuple>
	#include <typeindex>
	#include <type_traits>
	#include <unordered_map>
	#include <unordered_set>
#endif//=#include<bits/stdc++.h>
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<ai时,跳出
			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;
}
  • 27
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值