看守(rms模拟7-3)* * (推理)

题目描述

给出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;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值