贪心策略——项目利润

25 篇文章 0 订阅
21 篇文章 0 订阅

题目描述:
输入:
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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值