hihocoder 1150 基站选址

来源:互联网 发布:淘宝 手机 假货 编辑:程序博客网 时间:2024/05/01 18:14

首先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;}


0 0