[vijos1453] 曼哈顿距离

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\n",Ans);
	return 0;
}
posted @ 2019-08-21 15:20  OItby  阅读(165)  评论(0编辑  收藏  举报