1 条题解

  • 0
    @ 2025-11-18 8:52:11

    好的,我们根据这个代码来分析算法思路并生成题解和标签。


    算法思路

    这是一个利用对称性统计曼哈顿等边三角形的巧妙方法。

    核心观察

    在曼哈顿距离下,“等边三角形”实际上是一个等腰直角三角形,直角顶点在中间,两个腰长度相等。
    更具体地说:如果三点 A,B,CA,B,C 两两曼哈顿距离相等,那么它们构成一个“斜 45 度”的正方形的一半。


    方法步骤

    1. 枚举直角顶点 + 斜边方向
      对于每个可能的直角顶点 (i,j)(i,j),考虑它作为直角顶点,两个腰分别向右下和左下延伸长度 kk,得到另外两点 (i+k,j)(i+k,j)(i,j+k)(i,j+k),然后检查第三点 (i+k,j+k)(i+k,j+k) 是否存在。

    2. 前缀和优化
      定义 sum[i][j][k] 表示从 (i,j)(i,j) 向左上走 kk 步(曼哈顿距离)的矩形区域内的牛的数量(实际上是一个菱形区域)。
      这样可以在 O(1)O(1) 时间内知道某个菱形区域内是否有牛。

    3. 四次旋转计算
      因为等腰直角三角形的方向有 4 种(对应坐标轴的四个象限方向),所以将网格旋转 4 次,每次计算一种方向。

    4. 去重
      最后一部分的循环是去重:当三点共线时(水平或竖直),会被错误统计,需要减去这些情况。

      • 如果某行/列上有 3 个点共线且等距,会被错误算作三角形,需要减去。
      • 如果 4 个点共线且等距,会形成多个错误统计,需要减去对应数量。

    代码流程

    1. calc() 函数

      • 三重循环:i,ji,j 枚举直角顶点,kk 枚举腰长。
      • 用动态规划计算 sum[i][j][k] 表示左上菱形区域牛的数量。
      • 如果 (i+k,j)(i+k,j)(i,j+k)(i,j+k) 有牛,则加上 sum[i][j][k](即第三点 (i+k,j+k)(i+k,j+k) 所在菱形区域内的牛数)。
    2. 四次旋转

      • 第一次:原图。
      • 第二次:左右翻转。
      • 第三次:上下翻转。
      • 第四次:左右翻转(回到上下翻转后的左右翻转,即 180 度旋转+?)。
    3. 去重

      • 对每个点 (i,j)(i,j),统计它所在行和列上与之曼哈顿距离为 kk 的牛的数量 cnt[k]
      • 如果 cnt[k] == 3,说明有 3 个点共线等距,减去 1 个错误统计。
      • 如果 cnt[k] == 4,说明有 4 个点共线等距,减去 4 个错误统计(组合数 C43=4C_4^3 = 4)。

    复杂度

    • 前缀和与统计:O(N3)O(N^3)
    • 四次旋转:常数 4 倍
    • 去重:O(N3)O(N^3)
    • 总复杂度:O(N3)O(N^3),在 N300N \le 300 时可接受。

    算法标签

    #曼哈顿距离 #前缀和 #组合计数 #对称性 #几何
    

    关键点总结

    1. 曼哈顿等边三角形实际上是等腰直角三角形,且直角顶点在中间。
    2. 通过枚举直角顶点和腰长,用前缀和快速统计第三点存在的数量。
    3. 旋转网格处理所有方向。
    4. 最后要去掉共线情况的错误统计。

    • 1

    信息

    ID
    5402
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者