CodeVS4096 点的最小化距离

http://codevs.cn/problem/4096/

题意:平面直角坐标系中有N个整数点(Xi,Yi),再找出一个可以与其他点重合的整数点(X,Y),使得该点到N个点的距离之和最短。

这里的距离不是欧式距离,而是横坐标之差的绝对值加上纵坐标之差的绝对值。即若A(X1,Y1),B(X2,Y2),则dist(A,B)=|X1-X2|+|Y1-Y2|。

输出距离之和的最小值以及有多少个整数点可以被选择使得取到最小值。

对于一维上的,即给出X1...Xn,找一个合适的A值,使得S=|A-X1|+...+|A-Xn|最小,这个问题应该是非常经典的。

结论是这样的:按Xi的值排序得到新序列X'1...X'n,若n是奇数,则A应取X'[(n+1)/2],否则A的取值应该介于X'[n/2]和X'[n/2+1]。

对于n是偶数的情况,当A介于X'[n/2]和X'[n/2+1]时,S=(X'n-X'1)+(X'[n-1]-X'2)+...+(X'[n/2+1]-X'[n/2])。

否则,当A不介于该区间,一定有|A-X'[n/2]|+|A-X'[n/2+1]|>(X'[n/2+1]-X'[n/2]),而其余项的值也不会更小,故此时的S值不是最小的。

对于n是奇数的情况,由于当A=X'[(n+1)/2]时,|A-X'[(n+1)/2]|=0,任何非该值的A都会使得结果大于0,同时其余项的值也不会更小。

其余项的值不会更小是因为有|A-Xi|+|A-Xj|≥|Xi-Xj|。

对于二维的情况,显然这里的X和Y是可以分离开来分别做的。距离之和的最小值是容易求得的。

这里还需要输出有多少个可选的点,当n为奇数时应该只有1个,当n为偶数是,同样回归到一维的情况。

由于A是整数并且介于X'[n/2]和X'[n/2+1],显然可以有X'[n/2+1]-X'[n/2]+1个方案。

再推广到二维的情况,只要将两边的结果都求出来,然后根据乘法原理相乘即可。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
int x[10005],y[10005];
int n,i,j,k,t;
int abs(int a){
    if(a>=0) return a;
    else return -a;
}
int main(){
    scanf("%d",&n);
    for(i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]);
    sort(x+1,x+n+1);
    sort(y+1,y+n+1);
    j=x[n/2+1];
    k=y[n/2+1];
    t=0;
    for(i=1;i<=n;i++) t+=abs(j-x[i])+abs(k-y[i]);
    printf("%d ",t);
    if(n%2==1) printf("1\n");
    else printf("%d\n",(j-x[n/2]+1)*(k-y[n/2]+1));
    return 0;
}

你可能感兴趣的:(CodeVS4096 点的最小化距离)