题目大意:已知两个点集,从每个点集中各选出一个点,使得该两点之间的曼哈顿距离最小。
题目链接:http://uva.onlinejudge.org/external/15/1511.pdf
解题思路:我们设第1个点集的x坐标小于0,第二个点集的坐标大于0
由于曼哈顿距离的定义为
abs(x1-x2)+abs(y1-y2)=x2-x1+abs(y1-y2)
将y按照升序排序(两个集合一起排序) 枚举每一个点 同时更新x2-y2(第二个集合)的最小值tmp
由于已经排序 显然 对于每一个目前枚举的点(x1,y1)∈集合1,y1>=y2
所以距离变成x2-x1+y1-y2=x2-y2+y1-x1=min(tmp+y1-x1)
将数组翻转重新做一遍 这样就是选择集合1中的点的纵坐标<集合2中的点的纵坐标 的情况
过程中不断更新ans即可
这个题目貌似坏掉了 也没有办法提交
#include
#include
#include
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200005;
int t, n, m, a1, a2, a3, a4;
struct Point {
int x, y, flag;
} p[N];
bool cmp(Point a, Point b) {
return a.y < b.y;
}
int solve() {
int ans = INF;
sort(p, p + n + m, cmp);
int tmp = INF;
for (int i = 0; i < n + m; i++) {
if (p[i].flag)
tmp = min(tmp, p[i].x - p[i].y);
else
ans = min(ans, p[i].y - p[i].x + tmp);
}
tmp = INF;
reverse(p, p + n + m);
for (int i = 0; i < n + m; i++) {
if (p[i].flag)
tmp = min(tmp, p[i].x + p[i].y);
else
ans = min(ans, -p[i].x - p[i].y + tmp);
}
return ans;
}
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
p[i].flag = 0;
}
scanf("%d", &m);
for (int i = n; i < n + m; i++) {
scanf("%d%d", &p[i].x, &p[i].y);
p[i].flag = 1;
}
printf("%d\n", solve());
}
return 0;
}