切比雪夫距离

这篇博客介绍了如何利用曼哈顿距离来解决切比雪夫距离之和的问题。通过坐标系逆时针旋转45度并放大sqrt(2)倍,可以将切比雪夫距离转化为曼哈顿距离,从而实现O(nlogn)的时间复杂度求解。文章提供了一个示例,展示如何在给定的棋盘上计算两个玩家的国王之间的切比雪夫距离之和。
摘要由CSDN通过智能技术生成

曼哈顿距离

若点 \(A(x_1,y_1),B(x_2,y_2)\) 则两点间的曼哈顿距离为 \(|x_1-x_2|+|y_1-y_2|\)

已知 \(n\) 个点求两两之间的曼哈顿距离之和,易得 \(x\) 的贡献与 \(y\) 的贡献是分开的

可以用两次排序去绝对值 + 前缀和解决

复杂度 \(O(n\log n)\)

切比雪夫距离

曼哈顿距离是 4 向移动的最少步数,切比雪夫距离则是 8 向移动最少步数

即对于 \(A(x_1,y_1),B(x_2,y_2)\) 两点的切比雪夫距离为 \(\max(|x_1-x_2|,|y_1-y_2|)\)

问题:给定 \(n\) 个点,求两两之间的切比雪夫距离之和

此时 \(x,y\) 的贡献不能单独算了,怎么办?

转换

将原坐标系逆时针旋转 \(45^{\circ}\) ,再放大 \(\sqrt{2}\)

会发现:此(坐标系中的曼哈顿距离)是(原坐标系中切比雪夫距离)的 2 倍

考虑 \((x_1,y_1)\) 旋转后的坐标 \((x_2,y_2)\)

\(x_2=x_1\cos 45^{\circ}-y_1\sin 45^{\circ}=\dfrac{1}{\sqrt{2}}(x_1-y_1)\)

\(y_2=y_1\cos 45^{\circ}+x_1\sin 45^{\circ}=\dfrac{1}{\sqrt{2}}(x_1+y_1)\)

放大了 \(\sqrt{2}\) 倍,所以 \(x_2=x_1-y_1,y_2=x_1+y_1\)

转换成曼哈顿距离,同样 \(O(n\log n)\) 求,最后除以 2

给一个 \(n\times m\) 的棋盘,两个玩家有 'S''M' 两种国王,国王八向移动

传播值定义为玩家国王两两之间距离和,要分别求两个玩家的传播值

板子(确信)

code

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long uLL;
typedef long double LD;
typedef long long LL;
typedef double db;
const int N = 1005;
int n, m, tot;
struct poi { int x, y; } a[N * N];
LL tt, sm;
char mp[N][N];
inline bool cmp1(poi A, poi B) { return A.x < B.x; }
inline bool cmp2(poi A, poi B) { return A.y < B.y; }
inline void sol(char Ch) {
    tot = 0;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++)
            if (mp[i][j] == Ch) a[++tot] = (poi){ i - j, i + j };
    sort(a + 1, a + tot + 1, cmp1);
    sm = tt = 0;
    for (int i = 1; i <= tot; i++) sm += a[i].x * (i - 1) - tt, tt += a[i].x;
    sort(a + 1, a + tot + 1, cmp2), tt = 0;
    for (int i = 1; i <= tot; i++) sm += a[i].y * (i - 1) - tt, tt += a[i].y;
    printf("%lld ", sm / 2);
}
int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; i++) scanf("%s", mp[i] + 1);
    sol('M'), sol('S');
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值