2060 Taxi Cab Scheme

問題概要

タクシーのスケジュールが"時間 タクシーの出発位置 目的地"のリストにより与えられる。
このとき、スケジュールを満たすために必要なタクシーの最小の台数を求めよ。


タクシーの台数は500以下、
任意の二点(x,y) (v,w)をタクシーが移動するのにかかる時間は|x-v|+|y-w|分、
客を乗せたタクシーが次の客を乗せるためには、次の客の出発位置に1分以上前につかなければならないものとする。

解法

先日の模擬地区予選のMerry Christmasとほぼ同じ問題。
客Aを乗せたタクシーが次に客Bを運べるとき、A→Bに辺を張るものとすると、DAGができる。
DAGの最小パス被覆は、頂点を二倍にした二部グラフのマッチングにより解ける。

ソースコード

int n,m,sx[500],sy[500],dx[500],dy[500];
int t[500],move[500],p[1000];
char in[9]; vector<vi> e; bool v[1000];

bool match(int s)
{
	if(s<0)return 1;
	fr(i,e[s])if(!v[*i])
	{
		v[*i]=1;
		if(match(p[*i]))return p[s]=*i,p[*i]=s,1;
	}
	return 0;
}
int main()
{
	scanf("%d",&n);
	rep(it,n)
	{
		scanf("%d",&m);
		rep(i,m)
		{
			scanf("%s%d%d%d%d",in,sx+i,sy+i,dx+i,dy+i);
			t[i]=(in[0]-'0')*600+(in[1]-'0')*60+(in[3]-'0')*10+in[4]-'0';
			move[i]=abs(sx[i]-dx[i])+abs(sy[i]-dy[i]);
		}
		e.clear(); e.resize(2*m);
		rep(j,m)rep(i,j)if(t[j]>t[i]+move[i]+abs(dx[i]-sx[j])+abs(dy[i]-sy[j]))
		e[i].pb(m+j),e[m+j].pb(i);
		
		int ans=m;
		rep(i,2*m)p[i]=-1;
		rep(i,m)
		{
			rep(j,2*m)v[j]=0;
			if(match(i))ans--;
		}
		printf("%d\n",ans);
	}
	return 0;
}