题面
题目描述
小埋创建的公司即将开始IPO。为了更高的将价格将股票卖给风险投资公司,小埋希望在 IPO 之前公司开展一些项目增加自己的公司资本。由于资源有限,它只能在 IPO 之前完成最多
K
K
K个不同的项目。请帮助小埋设计完成最多
K
K
K 个不同的项目后得到的最大总资本的方式。
小埋有这样 n n n 个项目。对于每个项目 i i i ,它都有一个纯利润 a i a_i ai ,和启动该项目需要的最小资本 b i b_i bi 。
最初,小埋的资本为 w w w,当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本当中。
总而言之,从这 n n n 个项目当中选择最多 K K K 个不同的项目列表,以最大化最终的资本,并输出最终可获得的最多的资本。
输入格式
第一行输入三个整数 n , w , k n,w,k n,w,k
以下
n
n
n 行有
n
n
n 个项目,每一行有两个值
a
i
,
b
i
a_i,b_i
ai,bi,
a
i
a_i
ai 是投资获取的利润,
b
i
b_i
bi 是启动该项目的最小资本。
输出格式
输出一个整数,输出最大化后的资本。
样例
样例输入1
3 0 2
1 0
2 1
3 1
样例输出 1
4
样例输入 2
3 0 3
1 0
2 1
3 2
样例输出2
6
提示
1 ≤ n , k ≤ 1 0 5 1 \le n, k \le 10^5 1≤n,k≤105
0 ≤ w , b i ≤ 1 0 9 0 \le w,b_i \le 10^9 0≤w,bi≤109
0 ≤ a i ≤ 1 0 4 0 \le a_i \le 10^4 0≤ai≤104
题解
这一道题看上去需要使用动态规划,但是可以使用贪心很方便。
题目中的资产在不断变化,但由于要求在选择不超过 K K K 个项目的情况下收益尽可能高,贪心的思路就很明显:
在资产能够达到启动最低成本的所有项目中,纯利润越高的项目优先选择。
明确贪心思路后,思考一下就会发现,比较适合解决这种不断变化又要求最大值的,优先队列是一种很好的选择。
定义一个优先队列,用来存储资产能够达到最低成本的项目,在有项目可选且还没有选够
K
K
K 个项目的情况下,
不断地取出队首(当前剩余项目中资产能够达到其最低成本的纯利润最高的项 目),累加到资产中,
并且把当前资产能够达到最低成本的项目装入队列,不断地循环这些操作,就可以算出最终的答案。
代码实现:
#include <bits/stdc++.h>
using namespace std;
pair<int, int> f[100005];
bool cmp(pair<int, int> x, pair<int, int> y) {
return x.second < y.second;
}
int main() {
int n, w, k;
cin >> n >> w >> k;
for (int i = 1; i <= n; i ++) {
cin >> f[i].first >> f[i].second;
}
sort(f + 1, f + n + 1, cmp);
/*将最低资产升序排序,等到遍历时不需要将每一个项目都遍历一遍,而是只需要记录
上一次装入队列中的最后一个元素的下标,从下标 + 1处开始遍历
*/
priority_queue<pair<int, int> > q;
q.push({0, 0});
int p = 1, cnt = 0;
while (!q.empty()) {
while (p <= n and f[p].second <= w) {
q.push(f[p]);
p ++;
}
pair<int, int> cur = q.top();
q.pop();
w += cur.first;
cnt ++;
if (cnt == k) {
break;
}
}
cout << w << endl;
return 0;
}