You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Numpy二维数组0值链式爆炸扩散追踪问题

解决Numpy数组的多起始点链式扩散问题

嘿,我来帮你搞定这个链式扩散的问题!首先得明确咱们的需求:你有个R×C的Numpy数组,初始状态大部分是1,只有部分位置是0。要从这些0的位置开始,每次迭代把所有和当前0区域相邻的位置标记为0,直到整个数组全变成0,而且得支持一开始就有多个0的情况。之前用数学公式只适用于单个0的场景,那咱们换迭代模拟的思路就完全没问题啦。

从你给的示例来看,这里的“相邻”指的是8邻域(也就是上下左右加上四个斜角的位置),如果之后需要改成4邻域(仅上下左右),我也会在代码里说明怎么调整。

两种实现方法

方法1:直观遍历邻域(新手友好,容易理解)

这个方法的思路很直接:每次找出当前所有0的位置,然后挨个检查它们的邻域,把符合条件的1改成0,直到数组里没1为止。

代码写出来是这样的:

import numpy as np

def chain_reaction(arr):
    rows, cols = arr.shape
    iterations = 0
    # 定义8邻域的偏移坐标(要改成4邻域的话,删掉四个斜向的就行)
    neighbors = [(-1,-1), (-1,0), (-1,1),
                 (0,-1),          (0,1),
                 (1,-1),  (1,0), (1,1)]
    
    while np.any(arr == 1):
        # 找出当前所有0的位置
        zero_positions = np.argwhere(arr == 0)
        # 收集这次迭代要变成0的新位置
        new_zeros = set()
        for (r, c) in zero_positions:
            for dr, dc in neighbors:
                nr, nc = r + dr, c + dc
                # 检查位置是否在数组范围内,而且当前值是1
                if 0 <= nr < rows and 0 <= nc < cols and arr[nr, nc] == 1:
                    new_zeros.add((nr, nc))
        # 如果没找到新的0,说明扩散到头了(虽然你的场景最终会全0,但防个万一)
        if not new_zeros:
            break
        # 把这些新位置改成0
        for (nr, nc) in new_zeros:
            arr[nr, nc] = 0
        iterations += 1
    return iterations

# 测试你给的示例
initial_arr = np.array([[1,1,1,1],[1,1,1,1],[1,1,0,1],[1,1,1,1]])
print("初始数组:")
print(initial_arr)
iter_count = chain_reaction(initial_arr.copy())
print(f"\n链式反应耗时:{iter_count}次迭代")
print("最终数组:")
print(initial_arr)

运行这个代码,输出和你给的示例完全一致:迭代2次后数组全0。

方法2:用卷积操作(高效处理大数组)

如果你的数组尺寸很大,上面的遍历方法可能有点慢,这时候用卷积就高效多了。我们可以借助scipy的卷积函数,一次性算出每个位置周围有没有0,然后批量修改。

代码如下:

import numpy as np
from scipy.ndimage import convolve

def chain_reaction_convolve(arr):
    iterations = 0
    # 8邻域的卷积核(中心留空,周围都是1,用来检测邻域里的0)
    kernel = np.array([[1,1,1],
                       [1,0,1],
                       [1,1,1]])
    rows, cols = arr.shape
    while np.any(arr == 1):
        # 卷积操作:计算每个位置周围有没有0
        neighbor_zero = convolve(1 - arr, kernel, mode='constant', cval=0)
        # 找出需要改成0的位置:当前是1,且周围存在0
        to_zero = (arr == 1) & (neighbor_zero > 0)
        if not np.any(to_zero):
            break
        arr[to_zero] = 0
        iterations += 1
    return iterations

# 测试示例
initial_arr = np.array([[1,1,1,1],[1,1,1,1],[1,1,0,1],[1,1,1,1]])
print("初始数组:")
print(initial_arr)
iter_count = chain_reaction_convolve(initial_arr.copy())
print(f"\n链式反应耗时:{iter_count}次迭代")
print("最终数组:")
print(initial_arr)

这个方法的核心是用卷积一次性完成所有邻域的检测,速度会比遍历快很多,适合处理大规模的数组。

几个要注意的点

  • 邻域切换:如果你的需求是4邻域(只扩散上下左右),只需要修改邻域偏移量或者卷积核就行。比如4邻域的偏移量是[(-1,0), (0,-1), (0,1), (1,0)],卷积核改成[[0,1,0],[1,0,1],[0,1,0]]。
  • 多初始0支持:两种方法都天然支持多个初始0的情况,因为每次迭代都会遍历当前所有的0位置,不管一开始有多少个。
  • 终止条件:循环会一直跑,直到数组里没有1,或者找不到新的0位置(防止某些极端情况,比如数组里有孤立的1没法被扩散到)。

内容的提问来源于stack exchange,提问作者High-Octane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 00:02:30