题目大意
给定 \(d\) 维坐标的 \(n\) 个点,每个点表示为 \(d\) 个数值,求两点间最大距离
\(d\) 维两点间距离为 \(|x_1-y_1|+|x_2-y_2|+...+|x_d-y_d|\)
Sol
我们随便找两个点 \(A\),\(B\) 作为演示:
\[dis_{A,B}=|x_1-y_1|+|x_2-y_2|+...+|x_d-y_d|
\]
令 \(q\) 为 \(1\) 或 \(-1\),其实还可以写成:
\[dis_{A,B}=(qx_1-qy_1)+...+(qx_d-qy_d)
\]
(其中 \(q\) 不是同一个值)
如果这就是最大距离的话,我们改动任意一个
\(q\) 都会导致结果不优于
当前结果
所以我们可以表示成:
\[\max_{q\in{-1,1}} \{(qx_1-qy_1)+...+(qx_d-qy_d)\}
\]
可以给每个 \(q\) 单独赋值, 所得结果最大值即为最大距离
所以令 \(0\) 表示 \(1\) , \(1\) 表示 \(-1\) 压缩到一个 \(d\) 位二进制数中(跟状压dp很像)
我们只需要扫一遍 \([0,2^d-1]\) 就能找到答案
注意: 其中存在无用状态, 但一定会被最终结果覆盖
Code
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <vector>using namespace std;const int N = 1e6+10;
const int INF = 0x3f3f3f3f;int n , m;
vector<int> vec[N];int main() {ios::sync_with_stdio(false);cin.tie(nullptr); cout.tie(nullptr);cin >> n >> m;for(int i = 1 ; i <= n ; i ++)for(int j = 1 ; j <= m ; j ++) {int x; cin >> x;vec[i].push_back(x);}int res = 0;for(int state = 0 ; state < (1<<m)-1 ; state ++) {int minx = INF , maxx = -INF;for(int i = 1 ; i <= n ; i ++) {int v = 0;for(int j = 0 ; j < m ; j ++)if(state & (1 << j)) v += vec[i][j];else v -= vec[i][j];minx = min(minx , v);maxx = max(maxx , v);}res = max(res , maxx - minx);}cout << res << '\n';return 0;
}
闲话
在模拟赛中找到了 \(d\leq 8\) 的同款题目