一道简单的算法题
前情提要
博主的算法水平还是很垃圾的,但是今年选修的一门人工智能的课程上面我们学习了搜索算法,就有一道附加题是需要使用搜索算法来进行解答,经过我的查找验证后发现这是某OJ上的一道算法题,下面我就和大家来分享一下我的解决的心路历程和一些我的代码
问题描述
在一个 n ∗ m n*m n∗m的各自矩阵上,每个格子上的数字是0或1,数字1表示格子已经被污染了,数学0,表示格子是干净的。干净的格子可以通过上下左右四个方向和周围的干净格子连成一片干净的区域。如果这个干净的区域的周围完全被污染的格子包围,那么这片干净的区域中的所有格子都会被污染,也就是这片区域所有格子上的数字都会变成1。求最终这 n ∗ m n*m n∗m的格子矩阵的状态,每个格子是否被污染
问题输入
第一行两个数字n和m,表示格子矩阵的大小
接下来n行,每行m个用空格隔开的数字,每个数字非0即1,表示是否被污染
问题输出
输出n行,每行m个用空格隔开的数字,行末无空格。每个数字非0即1,表示格子相应格子是否被污染
范围说明
对于30%的数据有:1<=n.m<=20
对于100%的数据有:1<=n,m<=1000
示例
输入1
4 4
0 1 1 1
0 1 0 1
1 0 0 1
1 1 1 0
输出1
0 1 1 1
0 1 1 1
1 1 1 1
1 1 1 0
输入2
2 2
0 1
1 0
输出2
0 1
1 0
我最开始的解体思路
首先根据这个题目的描述,那么我想到的是,我要在中间对于干净的区域进行搜索,如果我搜索到的结果当中没有涉及边界,那么我就把这些区域给污染,如果搜索到了边界那么这样的区域就不能被污染
- 如何对于干净的区域进行搜索,我采用的是广度优先搜索,我把初始点选定为除了第一行最后一行和第一列和最后一列之外的几行和几列数据。起始也就是对于1<=i<=n-2和1<=j<=m-2进行搜索,这样的矩阵是(n-2)*(m-2)的大小。
- BFS的实现比较简单我采用的是一个数组,把它当作队列使用,然后每次取出它最前面的数据项,知道队列为0
- 如何添加数据项?如果它的上下左右四周有不在已经被访问过的列表中的,并且它的值为0,那么就把它加入队列中
- 如果我们触碰到了边界值,那么我们完成BFS搜索之后的这个区域都是不可被污染的,因为边界值肯定不会被全部被包围
语言说明
使用的是Python3.8
源代码(有注释)
import time#对于时间的import是为了计算时间引入的
fp1=open("input.txt","r")#读入数据
readAllText=fp1.readlines()#读入数据
for i in range(len(readAllText)):#对于readlines读入的数据进行处理
readAllText[i]=readAllText[i].strip()
nandm=readAllText[0].split()#对于读入第一行的数据进行处理,把它按空格分开
n=int(nandm[0])#第一行左边的数字,也是行数
m=int(nandm[1])#第一行后边的数字,也是列数
del readAllText[0]#删除处理过后的读入数据的第一行
for i in range(len(readAllText)):#把读入的每行的字符串拆分成数组
readAllText[i]=readAllText[i].split()
for i in range(len(readAllText)):#用了两层遍历把所有的字符串的0和1变成了整型的0和1
for j in range(len(readAllText[0])):
readAllText[i][j]=int(readAllText[i][j])
openTable=[]#搜索算法中的开始表
closeTable=[]#搜索算法中的访问过的表
areaTable=[]#这个存放当前搜索到的点的信息
startTime=time.time()#算法执行开始时间
def isInCloseTable(dot):#这个来判断dot节点是否存在于访问表中
for i in range(len(closeTable)):
if dot[0]==closeTable[i][0] and dot[1]==closeTable[i][1]:
return True
else:
return False
for i in range(1,n-1,1):#开始对第二行到第倒数第二行的遍历
for j in range(1,m-1