一道比较细节的贪心题
题意:
一个人可以选择在上午上班或者是在下午上班,不上班的时间可以摸鱼游玩
有n个室内的风景,m个室外的风景,这n+m个风景有一个漂亮值
对于这n+m个风景,如果第一次观看漂亮值转换为开心值比率为100%,如果重复观看,每重复一次就会变成之前的60%
对于室外的风景,下午观看会降到80%,上午观看不影响,如果在下午重复观看室外的风景,获得的开心值就是preVal * 80% * 60 %。(效果加成作用)
问这个人至少在白天工作k天( >= k),总共n天,最大能获得多少开心值
输入:
2 1 4 2
4 3
7
输出:
18.20
样例解释:
上午7上午7*0.6下午4下午3
7 + 7 * 0.6 + 4 + 3 == 18.20
很容易想到用优先队列维护两块(室内室外)的风景,每当观看过之后,就对这个值*0.6,因为已经观看过了
然后要在白天工作至少k天,所以也就意味着至少要在下午观赏k天
先来一份Wa的赛事代码,队友实现的非常OK,但是在我们讨论过程中还是细节没有考虑好
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
priority_queue<double,vector<double>,less<double> >q1;//室内
priority_queue<double,vector<double>,less<double> >q2;//室外
int main()
{
int n,m,k,t; cin >> n >> m >> t >> k;
for(int i=1;i<=n;i++)
{
double x; cin >> x;
q1.push(x);
}
for(int i = 1;i <= m;i++)
{
double x; cin >> x;
q2.push(x);
}
k = t - k;
double ans = 0;
for(int i = 1;i <= k;i++)
{
double x = q1.top();q1.pop();
double y = q2.top();q2.pop();
if(x >= y)
{
ans += x;
x *= 0.6;
}
else{
ans += y;
y *= 0.6;
}
q1.push(x);
q2.push(y);
}
k = t - k;
for(int i = 1;i <= n;i++)
{
double x = q1.top();q1.pop();
double y = q2.top();q2.pop();
if(x >= y * 0.8){
ans += x;
x *= 0.6;
}
else{
ans += y * 0.8;
y *= 0.6;
}
q1.push(x);
q2.push(y);
}
printf("%.2lf",ans);
return 0;
}
这份代码错就错在,将两部分进行分开考虑,实际上是不应该进行分开考虑的
也就是说:
所以最终Code就很容易啦:
int n,m,t,k;
priority_queue<double> quea,queb;
int main() {
cin >> n >> m >> t >> k;
for(int i=1; i<=n; i++) {
double t; cin >> t;
quea.push(t);
}
for(int i=1; i<=m; i++) {
double t; cin >> t;
queb.push(t);
}
double ans = 0;
k = t-k;
for(int i=1;i<=t;i++){
double topa = quea.top();
double topb = queb.top();
double mul = 1.0;
if(k <= 0) mul = 0.8;///afternoon
if(topa > topb * mul){
ans += topa;
quea.pop();quea.push(topa * 0.6);
}else{
ans += topb * mul;
queb.pop();queb.push(topb * 0.6);
k --;
}
}
printf("%.2lf
",ans);
return 0;
}//ac_code