目录
就补了能补的
C
题意:一个机场有N架飞机,正常来说飞机从第一分钟开始起飞,且每分钟只能起飞一架,现在飞机因延误,k分钟前不能有飞机起飞,每一架飞机起飞延误都会损失钱,让你来搞一搞怎么安排飞机损失成本最小
读完题目可以想到是贪心,关于贪心的证明我是看的这个大佬的:贪心证明的原博客
附上证明:首先,很容易想到这个题目利用贪心策略,所以我们首先要确定如何来进行贪心。每架飞机每延误一分钟都造成损失,那么我们只要保证每一分钟的损失都是最小的,那么结果一定是最优的。(正确性显然)
所以我们对当前的某一分钟进行分析,都有那些飞机可能在这一分钟产生损失呢?那些晚点的飞机和当前这一分钟正点的飞机都有可能产生损失。所以我们从这些飞机中选择出来一个每分钟损失最大的飞机,让它在这一分钟起飞,那么这一分钟这一架飞机就不会产生损失(正点的和晚点的都是),并且之后也不会在产生损失。其他的飞机(包括晚点的和正点的)都会在这一分钟产生损失。这样我们每一分钟的方案就确定下来了。
那么如何来实现呢?我们可以借助于STL中的优先队列(最大堆)来实现这个功能。先晚点的都压入到优先队列中,然后每分钟压入当前正点的飞机,并弹出这一分钟应该起飞的飞机。当没有正点的飞机时,逐个弹出队列中的元素即可。
————————————————
版权声明:本文为CSDN博主「Bug_Programmer」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42165981/article/details/81094323
解法:重点是飞机前k分钟不能起飞,而且延迟后起飞的飞机不能比对应的原本就要起飞的时间还早,根据上面的那个证明,我们可以得知从第k+1分钟到第k+n分钟起飞的要从已经晚点的和正好卡点的飞机中选择,选择延迟损失大的飞即可,用优先队列和set都可以
优先队列代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
struct f{
int hou;
int yuan;
int cost;
friend bool operator <(f a1,f a2)
{
return a1.cost<a2.cost;
}
}x[300010],w;
long long sum=0,n,k;
priority_queue<f>q;
int main()
{
cin>>n>>k;
for(long long i=1;i<=n;i++)
{
cin>>x[i].cost;
x[i].yuan=i;
}
long long i=1;
for(;i<=k;i++)//把前k分钟的压入优先队列,这样的才是延迟飞行的
{
q.push(x[i]);
}
for(;i<=n+k;i++)
{ if(i<=n)//!!这个条件必须写,因为最多n架,超过n之后就没飞机了
{
q.push(x[i]);//这是把正点的飞机压进去
}
w=q.top();
q.pop();
sum+=(i-w.yuan)*w.cost;//只有原时间小于i的还有等于i(正点)的飞机这一刻才能起飞
x[w.yuan].hou=i;//这是把对应的原时间改成延迟后的时间了,一定会把每个飞机的时间都改成延迟后的时间因为循环n次
}
cout<<sum<<endl;
for(long long p=1;p<=n;p++)
cout<<x[p].hou<<' ';
}
学set的时候学到了一个新的东西,就是set库下的函数:
lower_bound,作用:二分查找一个有序数列,返回第一个大于等于x的数的迭代器位置,如果没找到,返回末尾的迭代器位置 。
upper_bound,作用:二分查找一个有序数列,返回第一个大于x的数的迭代器位置,如果没找到,返回末尾的迭代器位置 。
set的代码:
#include<iostream>
#include<cstdio>
#include<set>
#include<algorithm>
using namespace std;
struct f{
int yuan;
int cost;
}x[300010],w;
long long sum=0,n,k,y[300010]={0};
bool cmp(f a,f b)
{
if(a.cost==b.cost)
return a.yuan>b.yuan;
else
return a.cost>b.cost;
}
set<int>q;
int main()
{
cin>>n>>k;
for(long long i=1;i<=n;i++)
{
cin>>x[i].cost;
x[i].yuan=i;
q.insert(k+i);
}
sort(x+1,x+1+n,cmp);
for(long long i=1;i<=n;i++)
{
long long w=*q.lower_bound(x[i].yuan);
sum+=(w-x[i].yuan)*x[i].cost;
y[x[i].yuan]=w;//这里由于x[i]在上面的快排里排序了,我们不能直接让x[i].yuan=w了,这样直接赋值对应的就不是一开始起飞的飞机了
q.erase(w);//应该找到原来的飞机对应序号赋上对应的延迟起飞的时间
}
cout<<sum<<endl;
for(long long p=1;p<=n;p++)
cout<<y[p]<<' ';
}