http://poj.org/problem?id=2926
一道裸题 计算k维空间两点最远曼哈顿距离 复杂度n*k*(2^k)
考虑二维平面两点(xi,yi) (xj,yj) 两者曼哈顿距离为|xi-xj|+|yi-yj| 去掉绝对值后可能有以下四种形式
(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)
发现两点对应维度坐标的符号相同 而曼哈顿距离最远的两个点之间同样如此 所以2^k枚举所有符号取向 再对n个点求出当前情况下的k个坐标相加之和 取最大最小值即可
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
double per[100010][10];
double maxx[50],minn[50];
int pre[50];
int n;
double getmax(double a,double b)
{
if(a>b) return a;
else return b;
}
double getmin(double a,double b)
{
if(a<b) return a;
else return b;
}
double solve()
{
double sum;
int i,j,k;
for(i=0;i<32;i++)
{
maxx[i]=-1000000000000000000.0;
minn[i]=1000000000000000000.0;
}
for(i=1;i<=n;i++)
{
for(j=0;j<32;j++)
{
sum=0.0;
for(k=0;k<5;k++)
{
if(j&pre[k]) sum+=per[i][k];
else sum-=per[i][k];
}
maxx[j]=getmax(maxx[j],sum);
minn[j]=getmin(minn[j],sum);
}
}
sum=0.0;
for(j=0;j<32;j++) sum=getmax(sum,maxx[j]-minn[j]);
return sum;
}
void init()
{
int i;
pre[0]=1;
for(i=1;i<=30;i++) pre[i]=2*pre[i-1];
}
int main()
{
int i,j;
init();
scanf("%d",&n);
for(i=1;i<=n;i++)
{
for(j=0;j<5;j++) scanf("%lf",&per[i][j]);
}
printf("%.2f\n",solve());
return 0;
}