编程之美2015资格赛 C 基站选址 (数学)

时间限制:
2000ms 单点时限:
1000ms 内存限制:
256MB

描述

需要在一个N × M的网格中建立一个通讯基站,通讯基站仅必须建立在格点上。

网格中有A个用户,每个用户的通讯代价是用户到基站欧几里得距离的平方。

网格中还有B个通讯公司,维护基站的代价是基站到最近的一个通讯公司的路程(路程定义为曼哈顿距离)。

在网格中建立基站的总代价是用户通讯代价的总和加上维护基站的代价,最小总代价。

输入

第一行为一个整数T,表示数据组数。

每组数据第一行为四个整数:N, M, A, B。

接下来的A+B行每行两个整数x, y,代表一个坐标,前A行表示各用户的坐标,后B行表示各通讯公司的坐标。

输出

对于每组数据输出一行”Case #X: Y”,X代表数据编号(从1开始),Y代表所求最小代价。

数据范围

1 ≤ T ≤ 20

1 ≤ x ≤ N

1 ≤ y ≤ M

1 ≤ B ≤ 100

小数据

1 ≤ N, M ≤ 100

1 ≤ A ≤ 100

大数据

1 ≤ N, M ≤ 107

1 ≤ A ≤ 1000

样例输入

2
3 3 4 1
1 2
2 1
2 3
3 2
2 2
4 4 4 2
1 2
2 4
3 1
4 3
1 4
1 3

样例输出

Case #1: 4
Case #2: 13

题解:只考虑用户的话,最优解的坐标为(x的平均值,y的平均值)。写出公式,然后求导即可证明。再考虑基站,由于是曼哈顿距离,写出公式,容易证明出基站是不影响最优解的坐标的。代码如下:

#include<iostream>
#include<algorithm>
#include<stdio.h>
#define nn 1100
typedef long long LL;
const int inf=0x3fffffff;
const LL inf64=(LL)inf*inf;
using namespace std;
LL sumx,psumx,sumy,psumy;
int n,m,A,B;
LL bx[nn],by[nn];
LL solvex(LL x,int id)
{
    return x*x*A+psumx-2*x*sumx+abs(x-bx[id]);
}
LL solvey(LL y,int id)
{
    return y*y*A+psumy-2*y*sumy+abs(y-by[id]);
}
int main()
{
    int t,i;
    int cas=1;
    scanf("%d",&t);
    LL x,y;
    while(t--)
    {
        scanf("%d%d%d%d",&n,&m,&A,&B);
        sumx=psumx=sumy=psumy=0;
        for(i=1;i<=A;i++)
        {
            scanf("%lld%lld",&x,&y);
            sumx+=x;
            psumx+=x*x;
            sumy+=y;
            psumy+=y*y;
        }
        LL ans=inf64;
        LL ansx,ansy;
        for(i=1;i<=B;i++)
        {
            scanf("%lld%lld",&bx[i],&by[i]);
            ansx=min(solvex(sumx/A,i),solvex(sumx/A+1,i));
            ansy=min(solvey(sumy/A,i),solvey(sumy/A+1,i));
            ans=min(ans,ansx+ansy);
        }
        printf("Case #%d: %lld\n",cas++,ans);
    }
    return 0;
}

    原文作者:madaidao
    原文地址: https://blog.csdn.net/madaidao/article/details/45154869
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞