题目大意:有两个集合A和B,A集合里面有n个点,B集合里面有m个点,A集合的所有的点的横坐标都比B集合的所有的点的横坐标还小
现在要求在A集合中和B集合中各选择一个点,使得这两点的曼哈顿距离达到最小
解题思路:分析式子abs(x1 - x2) + abs(y1 - y2)
这里假设(x1,y1)是A集合的点,(x2, y2)是B集合的点
因为B集合的点的横坐标都大于A集合的点的横坐标,所有abs(x1 - x2)可化作x2 - x1,现在就要讨论abs(y1 - y2)了
1.假设y2 >= y1,那么式子就变成了x2 - x1 + y2 - y1, 要达到做小,即x2 + y2 - (x1 + y1)要最小
2.假设y2 < y1,那么式子就变成了x2 - x1 + y1 - y2,即x2 - y2 + y1 - x1要达到最小
观察上面可得,要得到最小的值,就要维护某一个值,我们假设按y从小到大排序
第一种情况,就要维护 -(x1 + y1) 的最小值
第二种情况,要维护的是x2 - y2的最小值
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 200010;
const int INF = 0x3f3f3f3f;
struct point {
int x, y, flag;
}P[N];
int n, m;
bool cmp(const point a, const point b) {
return a.y < b.y;
}
void init() {
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 = 0; i < m; i++) {
scanf("%d%d", &P[i+n].x, &P[i+n].y);
P[i+n].flag = 1;
}
}
int solve() {
int ans = INF;
int tmp = INF;
sort(P, P + n + m, cmp);
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;
for(int i = 0; i < n + m; i++) {
if(P[i].flag) {
ans = min(ans, P[i].x + P[i].y + tmp);
}
else {
tmp = min(tmp, -P[i].x - P[i].y);
}
}
return ans;
}
int main() {
int test;
scanf("%d", &test);
while(test--) {
init();
printf("%d\n", solve());
}
return 0;
}