当前位置: 首页 > news >正文

二维差分算法高效解靶场问题

问题分析

给定一个 N×MN \times MN×M 的 01 矩阵(表示每个点是否被子弹中心击中)和子弹尺寸参数 l,rl, rl,r(子弹实际大小为 (2l+1)×(2r+1)(2l+1) \times (2r+1)(2l+1)×(2r+1)),需要输出最终靶子的状态矩阵(1 表示被摧毁,0 表示完好)。

关键规则
  1. 子弹中心被击中(输入矩阵中为 1)会摧毁以其为中心的矩形区域
  2. 摧毁范围:以中心点 (i,j)(i,j)(i,j) 为基准:
    • 行范围:[max⁡(0,i−r),min⁡(N−1,i+r)][\max(0, i-r), \min(N-1, i+r)][max(0,ir),min(N1,i+r)]
    • 列范围:[max⁡(0,j−l),min⁡(M−1,j+l)][\max(0, j-l), \min(M-1, j+l)][max(0,jl),min(M1,j+l)]
  3. 多个子弹区域可能重叠

高效算法:二维差分数组

使用二维差分数组可在 O(NM)O(NM)O(NM) 时间复杂度内高效标记所有被摧毁区域,优于暴力方法的 O(NM⋅(2l+1)(2r+1))O(NM \cdot (2l+1)(2r+1))O(NM(2l+1)(2r+1))

算法步骤
  1. 初始化差分数组

    • 创建大小为 (N+2)×(M+2)(N+2) \times (M+2)(N+2)×(M+2) 的二维数组 diff(多出的空间用于边界处理)
    • 初始化为 0
  2. 标记摧毁区域

    • 遍历输入矩阵的每个点 (i,j)(i,j)(i,j)
      if grid[i][j] == '1':row_start = max(0, i - r)row_end = min(N-1, i + r)col_start = max(0, j - l)col_end = min(M-1, j + l)# 差分标记diff[row_start][col_start] += 1diff[row_start][col_end+1] -= 1diff[row_end+1][col_start] -= 1diff[row_end+1][col_end+1] += 1
      
  3. 计算前缀和得到覆盖状态

    • 创建结果数组 res(大小 N×MN \times MN×M
    • 计算二维前缀和:
      for i in range(N):for j in range(M):# 前缀和公式res[i][j] = diff[i][j]if i > 0:res[i][j] += res[i-1][j]if j > 0:res[i][j] += res[i][j-1]if i > 0 and j > 0:res[i][j] -= res[i-1][j-1]# 转换为 0/1 状态res[i][j] = '1' if res[i][j] > 0 else '0'
      
  4. 输出结果

    • res 按行输出为字符串

示例演示

输入

2 2 1 1  # N=2, M=2, l=1, r=1
00
01       # 中心点 (1,1) 被击中

计算过程

  1. 子弹中心 (1,1) 的摧毁范围:[0,1]×[0,1][0,1] \times [0,1][0,1]×[0,1](整个矩阵)
  2. 差分标记:
    diff[0][0] += 1    → (0,0): +1
    diff[0][2] -= 1    → (0,2): -1(边界外)
    diff[2][0] -= 1    → (2,0): -1(边界外)
    diff[2][2] += 1    → (2,2): +1(边界外)
    
  3. 前缀和计算:
    坐标计算过程状态
    (0,0)1 + 0 + 0 - 01‘1’
    (0,1)0 + 1 + 0 - 01‘1’
    (1,0)0 + 1 + 0 - 01‘1’
    (1,1)0 + 1 + 1 - 11‘1’

输出

11
11

完整代码实现

def main():import sysdata = sys.stdin.read().splitlines()if not data: return# 解析第一行N, M, l, r = map(int, data[0].split())grid = data[1:1+N]# 初始化差分数组 (N+2) x (M+2)diff = [[0] * (M+2) for _ in range(N+2)]# 处理每个子弹中心for i in range(N):for j in range(M):if grid[i][j] == '1':row_start = max(0, i - r)row_end = min(N-1, i + r)col_start = max(0, j - l)col_end = min(M-1, j + l)# 差分标记diff[row_start][col_start] += 1diff[row_start][col_end+1] -= 1diff[row_end+1][col_start] -= 1diff[row_end+1][col_end+1] += 1# 计算二维前缀和res = [['0'] * M for _ in range(N)]for i in range(N):for j in range(M):# 继承上方和左侧的值if i > 0:diff[i][j] += diff[i-1][j]if j > 0:diff[i][j] += diff[i][j-1]if i > 0 and j > 0:diff[i][j] -= diff[i-1][j-1]# 转换为摧毁状态res[i][j] = '1' if diff[i][j] > 0 else '0'# 输出结果for row in res:print(''.join(row))if __name__ == "__main__":main()

算法复杂度

  • 时间复杂度O(NM)O(NM)O(NM)
    • 遍历输入矩阵:O(NM)O(NM)O(NM)
    • 差分标记操作:每个子弹中心 O(1)O(1)O(1)
    • 前缀和计算:O(NM)O(NM)O(NM)
  • 空间复杂度O(NM)O(NM)O(NM)
    • 差分数组:(N+2)×(M+2)(N+2) \times (M+2)(N+2)×(M+2)
    • 结果数组:N×MN \times MN×M

边界处理

  1. 矩阵边界
    • 使用 max(0, ...)min(N-1/M-1, ...) 确保坐标不越界
  2. 差分数组
    • 额外增加 2 行/列防止边界溢出
  3. 重叠区域
    • 差分累加自动处理多次覆盖

此算法能高效处理 103×10310^3 \times 10^3103×103 规模的数据,满足绝大多数应用场景需求。

http://www.dtcms.com/a/618408.html

相关文章:

  • 免费的企业黄页网站永久免费网站模板如何使用 如何修改吗
  • 如何在树莓派部署Nginx并实现无公网ip远程访问内网制作的web网站
  • 北京网站建设方案书专业的企业智能建站制造厂家
  • Hystrix架构原理与使用详解
  • bash Buffering
  • 区块链论文速读 CCF A--USENIX Security 2025(6)
  • SAP FICO工单成本明细报表
  • 网站建设需要看什么书长沙专业企业建站联系人
  • 金华永康网站建设手机优化怎么关闭
  • 斯坦福大学 | CS336 | 从零开始构建语言模型 | Spring 2025 | 笔记 | Lecture 9: Scaling laws 1
  • 银川网站网站建设数据库网站建设公司
  • MyBatis-Plus 三种数据库操作方式详解 + 常用方法大全
  • C++鼠标滑块轨迹 - 解决“京东滑块验证码”
  • 中山做网站的wordpress官网流量统计插件下载
  • 出口贸易公司网站怎么做煤棚网架加工厂
  • 如何自学建网站国内免备案网站空间
  • VS CMake报错Vbin32缺失?三步搞定
  • 用Rust实现一个简易的rsync(远程文件同步)工具
  • 如何用ps做照片模板下载网站哪里有网站建设
  • 【MIT-OS6.S081作业1.5】Lab1-utilities xargs
  • 文档抽取技术:通过OCR、NLP和机器学习技术,将非结构化的合同、发票等文档转化为结构化数据
  • 网站调研怎样做装修公司设计图
  • 西安网站制作优化顺德网站建设itshunde
  • 46 修改购物车数据
  • VUE的创建与配置
  • 44_FastMCP 2.x 中文文档之FastMCP集成:AWS Cognito 指南
  • 旅游网站建设市场分析公司就两个开发
  • 武昌手机网站59网一起做网站
  • 对抗拖库 —— Web 前端慢加密
  • BMAD-METHOD 开发方法论实践指南