首页 > 代码库 > UVA 1511 Soju(贪心)

UVA 1511 Soju(贪心)

UVA 1511 Soju

题目链接

题意:给定两个点集,要求两个点集各取一点曼哈顿距离最小值,保证点集1的x都小于0,点集2的x都大于0.

思路:由于x2 > x1所以只要考虑y值,如果一个y比另一个y大,那么就是y1 - y2,否则为y2 - y1,这样一来只要对这两种情况,分别进行两次排序贪心计算即可

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
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;
}