题目描述
给出D维空间的N个点,求曼哈顿距离最大的两个点的曼哈顿距离。两个D维的点(X1,X2,…,XD),(Y1,Y2,…,YD)的曼哈顿距离定义为|X1-Y1|+|X2-Y2|+…+|Xn-Yn|。
输入格式:
第一行两个整数N,D;
接下来N行,每行D个整数描述一个点的坐标。
【数据规模】
60%的数据,D<=2;
100%的数据,2<=N<=1000000,D<=4。
输出格式:
输出最大的曼哈顿距离。
输入样例#1:
4 2
2 1
1 4
4 5
5 3
输出样例#1:
6
题解:
一维时,|X1 - X2| = max(X1 - X2,X2 - X1)。
二维时,|X1 - X2| + |Y1 - Y2| = max(X1 - X2 + Y1 - Y2,X2 – X1 + Y1 - Y2,X1 - X2 + Y2 – Y1,X2 – X1 + Y2 – Y1)。
三维时,……
可以发现,对于D维时的两个点(X1,X2,…,XD)和(Y1,Y2,…,YD),将它们对应的绝对值去掉,那么就要分Xi – Yi 和Yi – Xi 进行讨论。如果Xi的符号是正的,那么Yi的符号就是负的;反之亦然。故可以枚举每一维的X的符号,用01表示,那么对应的Y的符号也随之确定。假设我们枚举答案中X的01情况,然后Y的01情况也确定,需要做的就是从所有的点中求出按照X的01情况得到的最大值,按照Y的01情况得到的最大值,然后两者相加就是在这种情况下的最优值,最后对于所有的可能情况取个最大值即可。
时间复杂度:枚举一个点在最后答案中每一维坐标的01(正负)情况的效率为O(2D),然后对于一种情况我们要从所有点中算出一个符合这种情况的最大值,效率为O(ND),故总的时间复杂度为O(2D*ND)。
空间复杂度:O(ND)
代码
#include<bits/stdc++.h>
#define F( i,a,b ) for( int i=( a );i<=( b );i++ )
#define F_2( i,a,b ) for( int i=( a );i>=( b );i++ )
#define N 1000001
#define M 10001
#define P 1000000007
#define LL long long
#define oo 0x7fffffff
using namespace std;
int read()
{
int f=1,s=0;
char ch=getchar();
while( ch<'0' || ch>'9' ) { if( ch=='-' ) f=-1; ch=getchar(); }
while( ch>='0' && ch<='9' ) { s=( s<<1 )+( s<<3 )+ch-'0'; ch=getchar(); }
return f*s;
}
int n,d;
int tot,ans,cnt;
int a[N][5];
int m[21];
int s[5];
int lab;
void fun( int dep,int k )
{
if( k )
s[dep]=1;
else
s[dep]=-1;
if( dep==d )
{
cnt++;
int t;
F( i,1,n )
{
t=0;
F( l,1,d )
t+=s[l]*a[i][l];
// cout<<t<<endl;
m[cnt]=max( m[cnt],t );
}
return;
}
F( i,0,1 )
fun( dep+1,i );
}
int main()
{
freopen( "jail.in","r",stdin );
freopen( "jail.out","w",stdout );
n=read();
d=read();
F( i,1,n )
{
F( j,1,d )
a[i][j]=read();
}
fill( m+1,m+20,-oo );
fun( 0,0 );
int b=1;
F( i,1,d-1 )
b*=2;
F( i,1,b )
ans=max( ans,m[i]+m[2*b-i+1] );
cout<<ans<<endl;
}