求最远曼哈顿距离,对于一个n维的空间,其中两点的曼哈顿距离为:|x1-y1|+|x2-y2|+|x3-y3|+|x4-y4|+……+|xn-yn| (两点的坐标分别为(x1,x2,……,xn)、(y1,y2,……,yn))
以下以二维平面为例研究:
设距离最远的两点为i,j,可知所求的最大距离必定有以下四种形式之一:
(xi-xj)+(yi-yj), (xj-xi)+(yi-yj), (xi-xj)+(yj-yi), (xj-xi)+(yj-yi) 变形一下,把相同点的坐标放到一起,
即 (xi+yi)-(xj+yj), (-xi+yi)-(-xj+yj), (xi-yi)-(xj-yj), (-xi-yi)-(-xj-yj) 再变一下,把中间变成‘+',
即 (xi+yi)+(-xj-yj), (-xi+yi)+(xj-yj), (xi-yi)+(-xj+yj),(-xi-yi)+(xj+yj)
由此,可以发现一个规律,即去绝对值之后把同一点的坐标放在一起,对应坐标的符号总是相反的,如(-xi+yi)与(xj-yj)。
假如我们用0表示负号,1表示正号,则(-xi+yi)与(xj-yj)两个括号内的符号可以表示为:01和10
当你多举几个例子之后,就会发现,对于一个确定的维数D,符号转化成的二进制数,它们的和总是一个定值,即2^d-1, 这就说明了,当我们知道了前一个点去绝对值之后的符号,就可以知道第二个点去绝对值后的符号是怎样的
于是只要对所有的点(xi,yi),依次计算出(xi+yi),(xi-yi),(-xi+yi),(-xi-yi)这四种形式,然后把每个点i算出来的这四种情况的最大值分别记录到一个数组max[]中,然后枚举每一种去绝对值的组合,组合后的最大值即为answer
再补充一点,这边是加,如果是减也一样,那就不是互补,而是相同,比如 i 点的符号是00,那么与之配对的 j 点坐标也应该是00
看的别人的题解啦 贴一下 https://blog.csdn.net/zstu_zlj/article/details/9953313
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF = 1e8;
struct node
{
int x[200];
}a[100010];
int T;
long long n,d,k,t,ans,s;
long long ma[1 >> 200],mi[1 >> 200];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&n,&d);
for(int i = 1;i <= n; ++i)
for(int j = 1;j <= d; ++j)
scanf("%lld",&a[i].x[j]);
k = 1 << d;
for(int j = 0;j < k; ++j)
{
ma[j] = -INF;
mi[j] = INF;
}
for(int i = 1;i <= n; ++i)
{
for(int j = 0;j < k; ++j)
{
t = j; s = 0;
for(int l = 1;l <= d; ++l)
{
if(t & 1)
s += a[i].x[l];
else s -= a[i].x[l];
t >>= 1;
}
ma[j] = max(ma[j],s);
mi[j] = min(mi[j],s);
}
}
ans = 0;
for(int i = 0;i <= k; ++i)
ans = max(ma[i] - mi[i],ans);
printf("%lld\n",ans);
}
return 0;
}