poj2060 Taxi Cab Scheme 最小路径覆盖

题意:

有n个顾客做出租车,给出每个人的出发时间,出发地与目的地的坐标,问最少要多少辆出租车能满足需要。

两地的距离为两地的曼哈顿距离,出租车一分钟可以行驶距离1。

读入数据按照出发时间升序给出。


思路:

对于两个顾客i和他前面的某个顾客j,如果i到达目的地的时间,加上从i的目的地到j的出发地的时间小于j的出发时间,i和j就能用一辆车满足。

所以,对于每个顾客i,枚举他前面的每一个顾客j,如果i和j能用一辆车满足,就从j到i连一条有向边,题目就转化成了最小路径覆盖问题。

最小路径覆盖=点数-最大匹配数


代码(1240K,79MS):

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

struct Point{
	int x, y;
	Point() {}
	Point(int a, int b) : x(a), y(b) {}
};

int T;
int n;
int tim[505];
int dist[505];
int mat[505];
int vis[505];
Point endPoint[505];
vector<int> edges[505];
// 两地的曼哈顿距离
int getDist(int x1, int y1, int x2, int y2) {
	return abs(x2 - x1) + abs(y2 - y1);
}

bool dfs(int k) {
	for (int i = 0; i < edges[k].size(); i++) {
		int j = edges[k][i];
		if (!vis[j]) {
			vis[j] = 1;
			if (!mat[j] || dfs(mat[j])) {
				mat[j] = k;
				return true;
			}
		}
	}
	return false;
}

int match() {
	int ans = 0;
	for (int i = 1; i <= n; i++) {
		memset(vis, 0, sizeof(vis));
		if (dfs(i)) ans++;
	}
	return ans;
}

int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%d", &n);
		int h, m;
		int x1, y1, x2, y2;
		for (int i = 1; i <= n; i++)
			edges[i].clear();
		for (int i = 1; i <= n; i++) {
			scanf("%d:%d", &h, &m);
			scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
			endPoint[i] = Point(x2, y2);	// 目的地
			tim[i] = h * 60 + m;	// 出发时间
			dist[i] = getDist(x1, y1, x2, y2); // 从出发地到目的地的距离
			for (int j = 1; j < i; j++) {
				if (dist[j] + getDist(endPoint[j].x, endPoint[j].y, x1, y1) + tim[j] < tim[i])
					edges[j].push_back(i);
			}
		}
		memset(mat, 0, sizeof(mat));
		int ans = n - match();
		printf("%d\n", ans);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值