多维空间的曼哈顿距离问题

1. 多维空间的任意两点间曼哈顿距离的最大值

POJ2926-Requirements

2 个点的距离的 4 种算法

(x1-x2) + (y1-y2),

(x1-x2) + (y2-y1),

(x2-x1) + (y1-y2),

(x2-x1) + (y2-y1)

改为:

(x1+y1) - (x2+y2) vs. (-x1-y1) - (-x2-y2)

(x1-y1) - (x2-y2) vs. (-x1+y1) - (-x2+y2)

我们发现上面同一行的两个式子只差一个负号,则对于所有 \(n\) 个点,求出下面 2 个值的最大最小值,相减即可

(x+y),

(x-y)

借助 bitset,我们令 0 表示系数为正,1 表示系数为负,状态 s~s 只要取一种求最大值最小值即可。

#include <iostream>
#include <bitset>
#include <algorithm>
using namespace std;
const int N = 1e5 + 7, D = 5;
const double INF = 1e18;
double a[N][D];
int n;
bitset<1<<D> st;
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < D; ++j) scanf("%lf", &a[i][j]);
    double ans = 0, mi, mx, sum;
    for (int s = 0; s < (1<<D); ++s) {
        if (st[s]) continue;
        st[s] = st[~s] = 1;
        mi = INF, mx = -INF;
        for (int i = 0; i < n; ++i) {
            sum = 0;
            for (int j = 0; j < D; ++j)
                if ((1<<j) & s) sum += a[i][j];
                else sum -= a[i][j];
            mi = min(mi, sum);
            mx = max(mx, sum);
        }
        ans = max(ans, mx - mi);
    }
    printf("%.2f", ans);
    return 0;
}

2. 多维空间中选取若干点的曼哈顿距离之和的最大值

巡回网络

\(k = 1\)

先来考虑 \(k=1\),也即一维的情况。

整个题的贡献可以拆为三个部分:固定点内部互相的贡献、固定点与可选点之间的贡献、可选点内部互相的贡献。

第一种贡献是个定值,可以预处理出来;第二种贡献相当于在选择可选点的时候每个点会有一个额外权值,所以我们主要考虑第三部分,也即可选点内部之间的贡献如何处理。

考虑可选点,由于我们要求的是最大的曼哈顿距离和,且注意到绝对值本身就可以理解成最大值:

\[|a|+|b|=\max(a+b,a-b,-a+b,-a-b). \]

也就是说,绝对值此时无关紧要,我们只需要考虑安排好每个数每一维正负号的贡献就好了。

举个例子,假设已经选好了 \(m\) 个点,那么你可以先排序成 \(x_1\le x_2\le \cdots\le x_m\),然后你按贡献计算 \(\sum_{i=1}^m(2i-m-1)x_i=\sum_{i\ne j}|x_i-x_j|\)。我们实际上只需要枚举 \(m!\) 种排列,然后将 \(\sum_{i=1}^m(2i-m-1)x_i\) 的最大值算出来。

所以在一维的情况下,自然可以设一个 DP 出来:设 \(f(i, S)\) 表示前 \(i\) 个点中,已经钦定了一些点位于 \(S\) 这些位置的情况下,所能产生的贡献最大值。此处的 \(S\) 应当是 \(m\) 位二进制数。也就是相当于用状压DP枚举了点坐标大小的 \(m!\) 种排列。

转移时,把第 \(i\) 个点放到第 \(p\) 个位置,贡献将会是 \((2p - m - 1)x _i + c _i\),其中 \(c _i\) 表示第 \(i\) 个点与其他固定点之间的贡献。如此状压 DP,复杂度是 \(O(n m2^m)\),其中 \(n\) 代表可选点数,也即 \(m + t\)

\(k = 2\)

其实本质上也没有什么区别,只是现在选择第 \(i\) 个点之后要同时考虑 \(x _i\)\(y _i\) 的位置。

\(f(i, S_1, S_2)\) 表示前 \(i\) 个点中,已经钦定了一些点的 \(x\) 坐标占据了 \(S_1\) 的位置,\(y\) 坐标占据了 \(S_2\) 的位置,所能产生的贡献最大值。

转移时,把第 \(i\) 个点的 \(x\) 坐标放到 \(p _1\) 的位置,\(y\) 坐标放到 \(p _2\) 的位置,贡献将会是 \((2p _1 - m - 1)x _i + (2p _2 - m - 1)y _i + c _i\),复杂度粗略估计一下大概是 \(O(nm^2 4^m)\),已经可以过了。

但是注意到,\(S _1\)\(S_2\) 互相之间是有限制的,因为他们总需要保证出现的点数相同,不可能会是 \(O(4 ^m)\) 级别的状态量。实际上考虑枚举两个状态中出现的点数 \(k\),状态量应当为

\[\sum _{k = 0}^m {m \choose k}^2, \]

这是 \(O(\frac {4^m} {\sqrt m})\) 的。

拓展:考虑一下有多次询问的情况,以及 \(k=3,4\) 的情况怎么做?

巡回网络高维版

posted @ 2025-08-15 11:00  飞花阁  阅读(22)  评论(0)    收藏  举报
//雪花飘落效果