codeforces round 433 D. Jury Meeting
题目大意:
输入n,m,k,分别代表城市的数量,城市编号1~n,航班的数量以及会议必须所有人员到会一起商议的天数,然后及时输入m行航班的信息,每一行输入d,f,t,c分别表示航班到站和始发的那一天(始发和到站是一天),f表示始发站,t表示目的地,c表示花费,然后f和t里必然有一个是0,表示要么是去0号城市,要么回到原来城市,题目要求就是,每个城市必须派人到0号城市参加会议,然后他们必须一块在0号城市k天,然后必须全部回到他们原来的城市才行(某个城市某个人到达0号城市之后可以愿意待多少天就待多少天,当然,回不去就尴尬了),让你求最小的花费,如果不能满足条件,输出-1;
基本思路:
最小费用分为0号城市的航班的费用和从0号城市飞回的费用,分别处理,然后贪心的话,就有一个问题,拿飞向0号城市的航班来说,到底是按照始发时间排序还是按照费用排序,想一下,如果按照费用排序,这个时间复杂度肯定过不了,那么就按照始发时间排序,这样,用一个dp数组记录总费用,下标是这n个航班的最晚始发时间,然后对于某一个最晚始发时间,最优的肯定是它和始发时间在它前面的最小费用了,然后就有这个dp【i】=min(dp【i-1】,dp【i】),这个点之前的最小费用就这样传递了过来,然后这样时间复杂度就是n,完全没问题;
反思与总结:
我只知道是贪心,并没有明确的贪心思路,看了题解才发现,类似的题目我也做过2个,真心菜,一定要扎实,首要目的是下次能a出这个题目啊;
代码如下:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll inf = 1e17; const int maxn = 2000000+10; const int maxx = 100000+10; struct Node { int d,f,t,c; bool operator<(const Node& a)const {return d<a.d;} }node[maxx]; ll dp1[maxn],dp2[maxn],b[maxn]; int main() { int n,m,k; while(scanf("%d%d%d",&n,&m,&k)==3) { for(int i=0;i<=maxn;i++) dp1[i]=inf,b[i]=-1; for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&node[i].d,&node[i].f,&node[i].t,&node[i].c); } sort(node+1,node+m+1); int cnt=0; ll sum=0; for(int i=1;i<=m;i++) { if(node[i].f==0) continue; if(b[node[i].f]==-1) { b[node[i].f]=node[i].c; sum+=node[i].c; cnt++; } else { if(b[node[i].f]>node[i].c) { sum-=b[node[i].f]; sum+=node[i].c; b[node[i].f]=node[i].c; } } if(cnt==n) dp1[node[i].d]=sum; } sum=0; cnt=0; for(int i=0;i<=maxn;i++) dp2[i]=inf,b[i]=-1; for(int i=m;i>=1;i--) { if(node[i].t==0) continue; if(b[node[i].t]==-1) { b[node[i].t]=node[i].c; sum+=node[i].c; cnt++; } else { if(b[node[i].t]>node[i].c) { sum-=b[node[i].t]; sum+=node[i].c; b[node[i].t]=node[i].c; } } if(cnt==n) dp2[node[i].d]=sum; } int sign; for(int i=1;i<=maxn;i++) if(dp1[i]!=inf) {sign=i;break;} for(int i=sign;i<=1000000;i++) dp1[i]=min(dp1[i],dp1[i-1]); for(int i=1000000;i>=1;i--) if(dp2[i]!=inf) {sign=i;break;} for(int i=sign-1;i>=1;i--) dp2[i]=min(dp2[i],dp2[i+1]); ll res=inf; for(int i=1;i<=1000000;i++) { if(dp1[i]==inf||dp2[i+k+1]==inf) continue; res=min(res,dp1[i]+dp2[i+k+1]); } if(res==inf) printf("-1\n"); else printf("%I64d\n",res); } return 0; }