题目大意:
输入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;
}