贪心算法一般可用于求局部最优解。
但对于全局,单纯的贪心考虑不到以后的影响,因此需要有反悔。
下面是例子:
7-5 股票问题
分数 20
全屏浏览题目
切换布局
作者 Mary
单位 河北农业大学
在某一天,你突然获得了可以预知每一天股票价格的超能力。在 第 i (i≤n)天,股票的价格为 ai,每一天你只能选择买入或卖出一只股票,或者什么都不做。请聪明的你思考一下,如何操作才能使赚到的钱最多呢?
输入格式:
输入分为两行。
第一行为 n (n≤105)。表示一共 n 天。
第二行有 n 个数,第 i 个数代表第 i 天的股票价格 a[i] (1≤a[i]≤106)。
输出格式:
输出答案,即 n 天后赚到的最多金钱数。
输入样例:
在这里给出一组输入。例如:
9
10 5 4 7 9 12 6 2 10
输出样例:
20
提示
在样例中,可以选择在第 2,3 天买入股票,在第 5,6 天选择卖出,获得的金钱为 −5−4+9+12=12,在第 8 天选择买入,第 9 天选择卖出,获得的金钱为 −2+10=8,所以总金钱为 20。可以证明,没有任何一种方式得到大于 20 的金钱数。
代码长度限制
16 KB
时间限制
400 ms
内存限制
64 MB
题解:此题可应用反悔贪心。开一个小顶堆(可用优先队列)将每天的价格与堆顶比较 如果>0,就表示可以赚点,记录下来。
代码如下:
#include<iostream>
#include<queue>
using namespace std;
int main(){
int n;
cin>>n;
vector<int>a(n);
priority_queue<int,vector<int>,greater<int> >q;
for(int i=0;i<n;i++)
cin>>a[i];
q.push(a[0]);
long long ans=0;
for(int i=1;i<n;i++){
q.push(a[i]);
if(!q.empty()&&q.top()<a[i]){
ans+=a[i]-q.top();
q.pop();
q.push(a[i]);
}
}
cout<<ans;
}
注意:当满足条件时,仍要将a[i]再次入堆。 例子如:2 4 8 8. 堆中一开始是2,最后是两个四,这样结果才是最大为10。