首先X,Y轴分开考虑,枚举B,对于坐标分成左边和右边,这两边都是满足凹函数的,可以三分求解,维护最小值
(不过据说这题数据很水,我模拟退火的也过了
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N = 105;
int ax[N * 10], ay[N * 10];
int t, n, m, an, bn;
int abss(int x) {
if (x < 0) return -x;
return x;
}
ll cal2(int u, int v, int *x) {
ll ans = 0;
ans += abss(u - v);
for (int i = 0; i < an; i++) {
int dx = u - x[i];
ans += (ll)dx * dx;
}
return ans;
}
ll cal(int l, int r, int v, int *x) {
while (r - l > 2) {
int midl = (l * 2 + r) / 3;
int midr = (l + 2 * r) / 3;
if (cal2(midl, v, x) < cal2(midr, v, x)) r = midr;
else l = midl;
}
ll ans = (1LL<<63) - 1;
for (int i = l; i <= r; i++) ans = min(ans, cal2(i, v, x));
return ans;
}
ll gao(int x, int y) {
ll ans = 0;
ans += min(cal(1, x, x, ax), cal(x, n, x, ax));
ans += min(cal(1, y, y, ay), cal(y, m, y, ay));
return ans;
}
int main() {
int cas = 0;
scanf("%d", &t);
while (t--) {
scanf("%d%d%d%d", &n, &m, &an, &bn);
for (int i = 0; i < an; i++) scanf("%d%d", &ax[i], &ay[i]);
ll ans = (1LL<<63) - 1;
int x, y;
for (int i = 0; i < bn; i++) {
scanf("%d%d", &x, &y);
ans = min(ans, gao(x, y));
}
printf("Case #%d: %lld\n", ++cas, ans);
}
return 0;
}