Description
给出N个D维空间的点。求出曼哈顿距离最大的两个点的曼哈顿距离。两个点(x1,x2,…,xd)、(X1,X2,…XD)的曼哈顿距离为|x1-X1|+|x2-X2|+…+|xd-XD|。
Input
第一行两个整数N,D(1<N<1000000,1≤D≤5)。接下来的N行,每行描述一个坐标点。
Output
曼哈顿距离最大的两个点的曼哈顿距离。
Sample Input
4 2
2 1
1 4
4 5
5 3
Sample Output
6
Hint
数据规模:
60%数据,1≤N≤1000000,1≤D≤2;
100%数据,1≤N≤1000000,1≤D≤5。
题解
先考虑一维的情况,
(|x_1-X_1|=max(~x_1-X_1~,~-x_1+X_1~)),
变形得:
(|x_1-X_1|=max(~x_1-X_1~,~(-x_1)-(-X_1)~));
规律不明显,再考虑二维的情况,
(|x_1-X_1|+|x_2-X_2|=max(~x_1-X_1+x_2-X_2~,~x_1-X_1-x_2+X_2~,~-x_1+X_1+x_2-X_2~,~-x_1+X-1-x_2+X_2~)),
还是变形得
(|x_1-X_1|+|x_2-X_2|=max(~(x_1+x_2)-(X_1+X_2)~,~(x_1-x_2)-(X_1-X_2)~,~(-x_1+x_2)-(-X_1+X_2)~,~(-x_1-x_2)-(-X_1-X_2)~))
这时,我们可以轻松地发现规律了,即(x[])与(X[])同号,再看一下数据规模,(1≤D≤5),正好可以用二进制。
用二进制表示正号和负号的排列,依次枚举每一种情况,更新(Ans=max(Ans,Max-Min))。
#include<iostream>
#include<cstdio>
using namespace std;
const int N=1000001,D=6,INF=9999999;
int p[N][D];
int main()
{
int n,d;
scanf("%d%d",&n,&d);
for(int i=1;i<=n;++i)
for(int j=1;j<=d;++j) scanf("%d",&p[i][j]);
int maxs,mins,YH,Res,Ans=-1;
YH=1<<d;
for(int i=0;i<YH;++i)
{
maxs=-INF,mins=INF;
for(int j=1;j<=n;++j)
{
Res=0;
for(int k=1;k<=d;++k)
if(i&(1<<(k-1))) Res+=p[j][k];
else Res-=p[j][k];
maxs=max(maxs,Res),mins=min(mins,Res);
}
Ans=max(Ans,maxs-mins);
}
printf("%d
",Ans);
return 0;
}