題意:有 n 個乘客需要乘出租車出行,給出他們出發時間,出發地點,目的地(input 保證資料按照出發時間升序給出),問最少需要安排多少輛車才能滿足他們的需求。
思路:我們把每個乘客的旅程看成一個點,那麼如果去搭載第 i 個人的車在把第 i 個人送到目的地後,立即啟程去第 j 個人的出發點,並且能在第 j 個人的出發時間前趕到,那麼這兩個人就只需要一輛車就可以滿足需要,我們就在點 i 和 點 j 之間建邊就好,依次類推,枚舉每兩個人的旅途,依次判斷然後建邊,最後求出最大二分匹配,再根據
最小路徑覆蓋 = 點數 - 最大二分匹配,
即可得到結果。
#include<cstdio>#include<cstring>#include<cmath>const int N = 510;struct point{ int time; int a,b,c,d;}p[N];struct Edge{ int s,e,next;}edge[N*N];int n,e_num,head[N],vis[N],match[N];void AddEdge(int a,int b){ edge[e_num].s=a; edge[e_num].e=b; edge[e_num].next=head[a]; head[a]=e_num++;}int dis(int i,int j){ if(i==j)return abs(p[i].a-p[i].c)+abs(p[i].b-p[i].d); else return abs(p[i].c-p[j].a)+abs(p[i].d-p[j].b);}int dfs(int a){ for(int k=head[a];k!=-1;k=edge[k].next){ int i=edge[k].e; if(!vis[i]){ vis[i]=1; if(match[i]==-1 || dfs(match[i])){ match[i]=a; return 1; } } } return 0;}int main(){ int t,i,j,h,m; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d:%d%d%d%d%d",&h,&m,&p[i].a,&p[i].b,&p[i].c,&p[i].d); p[i].time=h*60+m; } e_num=0; memset(head,-1,sizeof(head)); for(i=1;i<=n;i++){ for(j=i+1;j<=n;j++){ if(p[i].time+dis(i,i)+dis(i,j)<p[j].time) AddEdge(i,j); } } int cnt=0; memset(match,-1,sizeof(match)); for(i=1;i<=n;i++){ memset(vis,0,sizeof(vis)); if(dfs(i)) cnt++; } printf("%d\n",n-cnt); } return 0;}