CF853B Jury Meeting(dp)

来源:互联网 发布:在linux用yum安装jdk 编辑:程序博客网 时间:2024/06/09 05:48

把航班按出发时间从小到大排序。从前往后扫,求出dp[i]表示i时刻全都已出发的最小花费(i时刻全部已出发,也就是说可选航班是一个时间均小于i的前缀,在这些航班中选择n个人的最小花费,具体处理见代码)。类似的,从后往前扫,求出dp1[i]表示i时刻开始走,全部返回的最小花费(也就是说可选航班是一个时间均大于i的后缀)。然后枚举i时刻全部出发,则i+k+1时刻开始返回,更新答案。

#include <bits/stdc++.h>using namespace std;#define pa pair<int,int>#define ll long long#define inf 1LL<<60#define N 1000005inline int read(){    int x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x*f;}int n,m,k,mn[N],T=0;//dp1[i] i时刻回所有人的最小花费ll dp[N],dp1[N];//dp[i] i时刻出发所有人的最小花费。struct node{    int d,s,t,v;}a[N];inline bool cmp(node x,node y){return x.d<y.d;}int main(){//  freopen("a.in","r",stdin);    n=read();m=read();k=read();    for(int i=1;i<=m;++i)        a[i].d=read(),a[i].s=read(),a[i].t=read(),a[i].v=read(),T=max(T,a[i].d);    sort(a+1,a+m+1,cmp);int tot=0;ll sum=0;    memset(mn,0,sizeof(mn));    for(int i=1;i<=T;++i) dp[i]=inf;    for(int i=1;i<=m;++i){        if(a[i].s==0) continue;        if(mn[a[i].s]==0) mn[a[i].s]=a[i].v,tot++,sum+=a[i].v;        else if(a[i].v<mn[a[i].s]) sum+=a[i].v-mn[a[i].s],mn[a[i].s]=a[i].v;        if(tot==n) dp[a[i].d]=sum;    }int s=1;    while(dp[s]==inf&&s<=T) ++s;    if(s>T){puts("-1");return 0;}    for(int i=s+1;i<=T;++i) dp[i]=min(dp[i],dp[i-1]);    for(int i=1;i<=T;++i) dp1[i]=inf;memset(mn,0,sizeof(mn));    tot=0;sum=0;    for(int i=m;i>=1;--i){        if(a[i].t==0) continue;        if(mn[a[i].t]==0) mn[a[i].t]=a[i].v,tot++,sum+=a[i].v;        else if(a[i].v<mn[a[i].t]) sum+=a[i].v-mn[a[i].t],mn[a[i].t]=a[i].v;        if(tot==n) dp1[a[i].d]=sum;    }s=T;    while(dp1[s]==inf&&s>=1) --s;    if(s<1){puts("-1");return 0;}    for(int i=s-1;i>=1;--i) dp1[i]=min(dp1[i],dp1[i+1]);    ll ans=inf;    for(int i=1;i+k+1<=T;++i){        if(dp[i]==inf||dp1[i+k+1]==inf) continue;        ans=min(ans,dp[i]+dp1[i+k+1]);    }    if(ans==inf) puts("-1");    else printf("%I64d\n",ans);    return 0;}
原创粉丝点击