Codeforces Round #433 (Div. 2) D. Jury Meeting

本文介绍了一种解决特定问题的算法:一群人需要前往并停留于指定城市的最优航班安排方案。通过将航班按时间分类排序,算法确保了团队成员能以最低成本完成往返行程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

所有人要去0号城市,并且只坐飞机,飞机只有去0的和从0出发的,所有人要呆k天,问最小机票花费。

题解

对去的和返回的飞机分类排序,去的从早到晚,回来的从晚到早,处理每个时间上所有人去0的最小代价(由于排好序,所以选择时选的是时间最小的),从晚到早选返回的,所有人都满足时算一下代价,最后找出代价最小值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    char ch=getchar();int f=0;
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') {f=f*10+(ch^48);ch=getchar();}
    return f;
}
struct data
{
    int cost;
    int pla;
    int tim;
}come[100005],leave[100005];
int tot1,tot2,val[100005],finish_time,cou,val2[100005],cou2,finish_time2;long long sum,finish[1000005],sum2,ans=900000000000000000LL;
bool cmp(data x,data y)
{
    return x.tim<y.tim;
}
bool cmp2(data x,data y)
{
    return x.tim>y.tim;
}
int main()
{
    int n=read(),m=read(),k=read();
    for(int i=1;i<=m;i++)
    {
        int d=read(),f=read(),t=read(),c=read();
        if(f==0)
        {
            leave[++tot1].pla=t;
            leave[tot1].cost=c;
            leave[tot1].tim=d;
        }
        else if(t==0)
        {
            come[++tot2].pla=f;
            come[tot2].cost=c;
            come[tot2].tim=d;
        }
    }
    sort(come+1,come+tot2+1,cmp);
    sort(leave+1,leave+tot1+1,cmp2);
    for(int i=1;i<=tot2;i++)
    {
        if(!val[come[i].pla])
        {
            val[come[i].pla]=come[i].cost;
            sum+=come[i].cost;
            cou++;
            if(cou==n)
            {
                finish_time=come[i].tim;
                finish[come[i].tim]=sum;
            }
        }
        else
        {
            if(come[i].cost>=val[come[i].pla])
            continue;
            sum+=come[i].cost;
            sum-=val[come[i].pla];
            val[come[i].pla]=come[i].cost;
            if(cou==n)
            {
                finish[come[i].tim]=sum;
            }
        }
    }
    for(int i=finish_time;i<=1000000;i++)
    {
        if(finish[i]==0)
        finish[i]=finish[i-1];
    }
    //for(int i=1;i<=20;i++)
//  cout<<finish[i]<<" ";
    for(int i=1;i<=tot1;i++)
    {
        if(finish_time+k+1>leave[i].tim)
        break;
        if(!val2[leave[i].pla])
        {
            cou2++;
            val2[leave[i].pla]=leave[i].cost;
            sum2+=leave[i].cost;
            if(cou2==n&&finish_time+k<=leave[i].tim)
            {
                ans=min(ans,sum2+finish[leave[i].tim-k-1]);
            }
        }
        else
        {
            if(leave[i].cost>=val2[leave[i].pla])
            continue;
            sum2+=leave[i].cost;
            sum2-=val2[leave[i].pla];
            val2[leave[i].pla]=leave[i].cost;
            if(cou2==n)
            {
                ans=min(ans,sum2+finish[leave[i].tim-k-1]);
            }
        }
    }
    if(ans==900000000000000000LL||!finish_time||cou2!=n||cou!=n)
    puts("-1");
    else cout<<ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值