题目描述:
输入:
cost[]:每个项目的花费
profits[]:每个项目的利润(纯利润)
k:最多能做k个项目
w:表示初始资金
输出:最后获得的最大钱数
说明:一次只能做一个项目,且做完一个之后马上就能获得收益,可以支持做下一个项目
/*
贪心策略:当资金有限时如何选择那个项目使得挣的钱最多
算法思想:
(1)将所有项目按照花费值costs加入到小根堆中
(2)从小根堆中取出可以做的项目(当前的花费值小于初始资金w)按照利润值profits加入到大根堆中
(3)开始做项目,更新w的值;直到做满k次,或者新的w值仍不满足做新的项目(资金不够,不足以支撑新的项目)
*/
/*
测试用例:
4(项目总数)
5 10 6 20 (costs)
3 2 4 9 (profits)
7 (初始资金)
2 (项目执行最多次数)
输出:14
算法思想:按照costs最低入小根堆(全部项目);从小根堆中取出costs低于已有资金(初始资金+做项目完成收益)
的项目,按照profits最高入大根堆,并做项目;直到已有资金不足以支持做下一个项目或者项目次数达到k时,说明
此时收益最大
*/
#include<iostream>
#include<queue>
using namespace std;
struct Node{
int c;//收益
int p;//花费
Node(int cost, int profit){
this -> c = cost;
this -> p = profit;
}
};
//小根堆只比较花费,不用比较利润
struct MinCostComparator{
bool operator()(Node a, Node b){
return a.c > b.c;
}
};
//大根堆只比较利润,不用比较花费
struct MaxProfitComparator{
bool operator()(Node a, Node b){
return a.p < b.p;
}
};
int MaxProfits(int w, int k, int *costs, int *profits, int n){
priority_queue<Node*, vector<Node>, MinCostComparator > MinCostsQue ;//按照costs小的节点入小根堆
priority_queue<Node*, vector<Node>, MaxProfitComparator > MaxProfitsQue ;//按照profits大的节点入大根堆
//将所有的项目加到小根堆中去
for(int i = 0; i < n; i ++){
Node *node = new Node(costs[i], profits[i]);
MinCostsQue.push(*node);
}
//最多做k次项目
for(int s = 0; s < k; s ++){
while(!MinCostsQue.empty() && MinCostsQue.top().c <= w){
Node topQue = MinCostsQue.top();
MaxProfitsQue.push(topQue); //将小根堆中的节点加入到大根堆中
MinCostsQue.pop();
}
if(MaxProfitsQue.empty()){ //做的项目还未达到k次就必须停止(跟数据状况有关)
return w;
}
w += MaxProfitsQue.top().p;
MaxProfitsQue.pop();
}
return w;
}
//for test
int main()
{
int n;//n代表项目数
cin>>n;
int *costs = new int[n];//costs代表每个项目对应的消费
int *profits = new int[n];//profits代表每个项目对应的收益
for(int i = 0; i < n; i ++){
cin>>costs[i];
}
for(int j = 0; j < n; j ++){
cin>>profits[j];
}
int w, k;//w为初始本金,k为项目最多次数
cin>>w>>k;
cout<<MaxProfits(w,k,costs,profits,n)<<endl;
return 0;
}