版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
在平面上有n个整点(横纵坐标都是整数)
牛牛想找到一个整点,使得这个点,到所有点的距离之和最小。
两个点的距离定义为从一个点走到另一个点的最小步数。
其中每步可以走向相邻8个点(上,下,左,右,左上,左下,右上,右下,类似国际象棋中的王)走一步。
输出这个最小的距离之和。
和这个点选择的方案数。(即有多少个点,可以达到这个最小的距离)
对于100%的数据,1 <= n <= 100000,|x|, |y| <= 1000000000
对于40%的数据,1 <= n <= 100,|x|, |y| <= 100
对于以上每部分数据,都有50%的数据n是奇数。
注意数据范围是x和y的绝对值,x和y可以是负数。
输入
第一行一个整数n
接下来n行,每行两个整数x, y。描述一个点。
输出
第一行输出最小的距离之和。
第二行输出有多少个点,可以达到这个最小距离。
输入样例
4
2 1
1 2
0 1
1 0
输出样例
4
5
曼哈顿距离与切比雪夫距离及其相互转
语法知识:
n&1:
当n为奇数:1
当n为偶数:0
n^1:
当n为奇数:n-1
当n为偶数:n+1
(n&1)^1:
当n为奇数:0
当n为偶数:1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 100005
int n;
//小写x,y为曼哈顿距离,大写为切比雪夫距离
ll sum[2][2],ans,dis,x[N],y[N],X[N],Y[N],_X,_Y;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
int main()
{
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>x[i]>>y[i];
//原坐标系中的曼哈顿距离==新坐标系中的切比雪夫距离
X[i]=x[i]-y[i];
Y[i]=x[i]+y[i];
}
//
sort(X+1,X+n+1);
sort(Y+1,Y+n+1);
ll a=X[(n+1)/2],b=X[(n+2)/2];
if(a==b)
sum[0][a&1]=1;
else
{
sum[0][0]=((b-((b&1)^1))-(a+((a&1)^1)))/2+((b&1)^1)+((a&1)^1);
sum[0][1]=((b-(b&1))-(a+(a&1)))/2+(b&1)+(a&1);
}
a=Y[(n+1)/2];b=Y[(n+2)/2];
if(a==b)
sum[1][a&1]=1;
else
{
sum[1][0]=((b-((b&1)^1))-(a+((a&1)^1)))/2+((b&1)^1)+((a&1)^1);
sum[1][1]=((b-(b&1))-(a+(a&1)))/2+(b&1)+(a&1);
}
//
ans=sum[0][0]*sum[1][0]+sum[0][1]*sum[1][1];
if(ans==0)
{
ll DIS=1e18;
for(int i=0;i<4;i++)
{
_X=X[(n+1)/2]+dir[i][0];
_Y=Y[(n+1)/2]+dir[i][1];
for(int i=1;i<=n;i++)
dis+=abs(X[i]-_X)+abs(Y[i]-_Y);
if (dis<DIS)
{
DIS=dis;ans=1;
}
else if(dis==DIS)
ans++;
dis=0;
}
cout<<(DIS/2)<<"\n"<<ans;
return 0;
}
_X=X[(n+1)/2];
_Y=Y[(n+1)/2];
if(_X+_Y&1)
{
if(_X<X[(n+2)/2])
_X++;
else
_Y++;
}
for(int i=1;i<=n;i++)
dis+=abs(X[i]-_X)+abs(Y[i]-_Y);
cout<<(dis/2)<<"\n"<<ans;
return 0;
}