做项目的最大收益问题

做项目的最大收益问题

题目描述

给定两个整数W和K,W代表你拥有的初始资金,K代表你最多可以做K个项目。再给定两个长度为N的正数数组costs[]和profits[],代表一共有N个项目,costs[i]和profits[i]分别表示第i号项目的启动资金与做完后的利润(注意是利润,如果一个项目的启动资金为10,利润为4,代表该项目最终的收入为14)。你不能并行只能串行地做项目,并且手里拥有的资金大于或等于某个项目的启动资金时,你才能做这个项目。该如何选择做项目,能让你最终的收益最大?返回最后能获得的最大资金

[要求]

时间复杂度为 O ( k log ⁡ n ) O(k \log n) O(klogn),空间复杂度为 O ( n ) O(n) O(n)

输入描述:

第一行三个整数N, W, K。表示总的项目数量,初始资金,最多可以做的项目数量
第二行有N个正整数,表示costs数组
第三行有N个正整数,表示profits数组

输出描述:

输出一个整数,表示能获得的最大资金

示例1
输入
4 3 2
5 4 1 2
3 5 3 2
输出
11
说明
初始资金为3,最多做两个项目,每个项目的启动资金与利润见costs和profits。最优选择为:先做2号项目,做完之后资金增长到6,。然后做1号项目,做完之后资金增长到11。其他的任何选择都不会比这种选择好,所以返回11
备注:

1 ⩽ K ⩽ N ⩽ 1 0 5 1 \leqslant K \leqslant N \leqslant 10^5 1KN105
1 ⩽ W , c o s t s [ i ] , p r o f i t s [ i ] ⩽ 1 0 9 1 \leqslant W, costs[i], profits[i] \leqslant 10^9 1W,costs[i],profits[i]109


题解:

构建两个堆,一个大跟堆,一个小根堆。对 cost 构建小根堆,把可做项目的收益放到大根堆,然后从大根堆中取出元素累加,再从小根堆中寻找可以做的项目,最多循环K次或没有可做项目则停止。

代码:
#include <cstdio>
#include <queue>

using namespace std;

const int N = 100000;

typedef pair<int, int> PII;

struct cmp {
    bool operator() ( const PII& p1, const PII& p2 ) const {
        return p1.first > p2.first;
    }
};

int profit[N];
int n, w, k;
priority_queue< PII, vector<PII>, cmp > p1;
priority_queue<int> p2;

int main( void ) {
    scanf("%d%d%d", &n, &w, &k);
    for ( int i = 0; i < n; ++i ) {
        int c;
        scanf("%d", &c);
        p1.push( {c, i} );
    }
    for ( int i = 0; i < n; ++i ) scanf("%d", profit + i);
    long long ret = w;
    while ( k -- ) {
        while ( p1.size() && p1.top().first <= ret ) {
            p2.push(profit[ p1.top().second ]);
            p1.pop();
        }
        if ( p2.empty() ) break;
        ret += p2.top();
        p2.pop();
    }
    return 0 * printf("%lld\n", ret);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值