Description
给出二维平面的 n n 个点的坐标,定义两点之间距离为曼哈顿距离,要求从这个点中选一个点使得其他点到该点距离之和最小
Input
第一行一整数 T T 表示用例组数,每组用例首先输入一整数表示点数,之后 n n 行每行输入两个整数表示第 i i 个点的横纵坐标
Output
输出最小距离和
Sample Input
4
6
-4 -1
-1 -2
2 -4
0 2
0 3
5 -2
6
0 0
2 0
-5 -2
2 -2
-1 2
4 0
5
-5 1
-1 3
3 1
3 -1
1 -1
10
-1 -1
-3 2
-4 4
5 2
5 -4
3 -1
4 3
-1 -2
3 4
-2 2
Sample Output
26
20
20
56
Solution
先把所有点按横坐标排序得到 n n 个不减的横坐标,记
sumi+1=∑j=1i−1(xi+1−xj)+xi+1−xi+∑j=i+1n(xj−xi+1)=sumi+(2i−n)⋅(xi+1−xi) s u m i + 1 = ∑ j = 1 i − 1 ( x i + 1 − x j ) + x i + 1 − x i + ∑ j = i + 1 n ( x j − x i + 1 ) = s u m i + ( 2 i − n ) ⋅ ( x i + 1 − x i )
以此 O(n) O ( n ) 即可得到 sum s u m 序列,即一个点被选中后其横坐标对答案的贡献,同理按纵坐标排序求出每个点纵坐标对答案的贡献,两者相加取最小值即为答案
Code
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=100005;
struct node
{
int x,y,id;
}a[maxn];
ll sum[maxn],ans;
bool cmpx(node a,node b)
{
return a.x<b.x;
}
bool cmpy(node a,node b)
{
return a.y<b.y;
}
int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
a[i].id=i;
}
sort(a+1,a+n+1,cmpx);
ll temp=0;
for(int i=2;i<=n;i++)temp+=a[i].x-a[1].x;
sum[a[1].id]=temp;
for(int i=2;i<=n;i++)
{
temp+=(ll)(2*(i-1)-n)*(a[i].x-a[i-1].x);
sum[a[i].id]=temp;
}
sort(a+1,a+n+1,cmpy);
temp=0;
for(int i=2;i<=n;i++)temp+=a[i].y-a[1].y;
sum[a[1].id]+=temp;
for(int i=2;i<=n;i++)
{
temp+=(ll)(2*(i-1)-n)*(a[i].y-a[i-1].y);
sum[a[i].id]+=temp;
}
ll ans=sum[1];
for(int i=2;i<=n;i++)ans=min(ans,sum[i]);
printf("%lld\n",ans);
}
return 0;
}