UVA1201/POJ2060 Taxi Cab Scheme

题意

给定m个客人的出发时间和起点,终点,问最少用几个出租车可以完成任务,出租车需要在出发前一分钟到达起点。坐标(x,y),时间花费|x1-x2|+|y1-y2|。

 0 < M < 500,出发时间00:00 to 23:59

题解

如果在送完一个客人之后还能够去送另一个客人,肯定是最好的。所以把一个客人拆成两个点:在起点和在终点,如果在终点的点能够再去送在起点的点就连边,最后ans=n-最大匹配数,因为每增加一个匹配就可以少用一辆出租车。

把时间全部弄成分钟制会好处理一点。

#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include <algorithm>
using namespace std;

const int maxn=1005;
int t,n;
int timer,vis[maxn],match[maxn];
vector<int> e[maxn];
struct point{
  int h;
  int x,y;
}a[maxn];

void init(){
  timer=0;
  memset(vis,0,sizeof(vis));
  memset(match,0,sizeof(match));
  for(int i=1;i<=n;i++) e[i].clear();
}

void get(int i){
  int h,m,x,y,xx,yy;
  scanf("%d:%d%d%d%d%d",&h,&m,&x,&y,&xx,&yy);
  h=h*60+m;
  a[i]=(point){h,x,y};
  h+=abs(x-xx)+abs(y-yy);
  a[i+n]=(point){h,xx,yy};
}

bool check(point a,point b){
  return a.h+abs(a.x-b.x)+abs(a.y-b.y)<b.h;
}

void make_edge(){
  for(int i=n+1;i<=2*n;i++)
   for(int j=n;j;j--){
     if(!check(a[i],a[j])) continue;
     e[j].push_back(i);
   }
}

bool dfs(int u){
  if(vis[u]==timer) return false;
  vis[u]=timer;
  for(unsigned int i=0;i<e[u].size();i++){
    int v=e[u][i];
    if(!match[v]||dfs(match[v])){
      match[v]=u;
      return true;
    }
  }
  return false;
}

int main(){
  scanf("%d",&t);
  while(t--){
    scanf("%d",&n);
    init();
    for(int i=1;i<=n;i++)
      get(i);
    make_edge();
    int ans=0;
    for(int i=1;i<=n;i++){
      timer++;
      if(dfs(i)) ans++;
    }
    printf("%d\n",n-ans);
  }
}
View Code

 

posted @ 2019-08-08 16:39  _JSQ  阅读(90)  评论(0编辑  收藏  举报