99.岛屿数量(深搜):
思路:
分析题目可知要求的是岛屿的数量,实际思路只需要先遍历一遍矩阵,遍历过程中,让节点用深搜或者广搜给能接触到的陆地都标记上,那么当深搜/广搜结束,再遍历到没有标记过的节点时,说明是新陆地,计数器加1。
深搜代码1
dp = [[1, 0], [0, 1], [-1, 0], [0, -1]] # 节点的上下左右位置
def dfs(grid, visited, x, y):
for i in range(4):
nextx = x + dp[i][0]
nexty = y + dp[i][1]
if nextx < 0 or nextx >= len(grid) or nexty < 0 or nexty >= len(grid[0]): # 越界
continue
if not visited[nextx][nexty] and grid[nextx][nexty]: # 是没有访问过的陆地节点
visited[nextx][nexty] = True
dfs(grid, visited, nextx, nexty)
def main():
n, m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
result = 0 # 记录陆地数目
visited = [[False] * m for _ in range(n)]
for x in range(n):
for y in range(m):
if not visited[x][y] and grid[x][y]:
visited[x][y] = True # 这里要记得设置为True
result += 1 # 找到了新的陆地
dfs(grid, visited, x, y)
print(result)
if __name__ == '__main__':
main()
深搜代码2
dp = [[1, 0], [0, 1], [-1, 0], [0, -1]]
def dfs(grid, visited, x, y):
if visited[x][y] or grid[x][y] == 0: # 访问过/海水
return
visited[x][y] = True
for i in range(4):
nextx = x + dp[i][0]
nexty = y + dp[i][1]
if nextx < 0 or nextx >= len(grid) or nexty < 0 or nexty >= len(grid[0]): # 越界
continue
#if not visited[nextx][nexty] and grid[nextx][nexty]:
# visited[nextx][nexty] = True
dfs(grid, visited, nextx, nexty)
def main():
n, m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
result = 0 # 记录陆地数目
visited = [[False] * m for _ in range(n)]
for x in range(n):
for y in range(m):
if not visited[x][y] and grid[x][y]:
# visited[x][y] = True # 这里要记得设置为True
result += 1 # 找到了新的陆地
dfs(grid, visited, x, y)
print(result)
if __name__ == '__main__':
main()
代码1和代码2的区别在于,代码1调用dfs的条件判断放在了代码2的边界条件位置。
代码1的写法是: 当前节点是否合法已经判断完了,visited设置为True已经在上一个dfs中设置了;而进入下一个dfs的节点,其是否合法已经在调用dfs前判断完了
代码2的写法是: 只要节点不越界,就调用dfs,至于合法判断,在dfs的临界条件处判断,visited设置在合法判断之后设置
99.岛屿数量(广搜):
思路:
本题就是上一题,只是深搜换成广搜,一般用队列完成广搜,此处广搜也有两种,1是先判断节点是否合法,合法再设置visited和加入队列;2是先把节点加入队列,出队列时再判断是否合法和设置visited。
2会导致一个问题,会出现节点重复入队的情况,如下图
因此只采用1,即先判断节点是否合法,再设置visited和入队
from collections import deque
direction = [[1, 0], [0, 1], [-1, 0], [0, -1]]
def bfs(grid, visited, x, y):
que = deque()
que.append([x, y])
while len(que) != 0:
curx, cury = que.popleft()
for i in range(4):
nextx, nexty = curx + direction[i][0], cury + direction[i][1]
if nextx < 0 or nextx >= len(grid) or nexty < 0 or nexty >= len(grid[0]): # 越界
continue
if not visited[nextx][nexty] and grid[nextx][nexty]:
visited[nextx][nexty] = True
que.append([nextx, nexty])
def main():
n, m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
visited = [[False] * m for _ in range(n)]
result = 0 # 记录陆地数
for x in range(n):
for y in range(m):
if not visited[x][y] and grid[x][y]:
visited[x][y] = True
result += 1
bfs(grid, visited, x, y)
print(result)
if __name__ == '__main__':
main()
100.岛屿的最大面积:
深搜
深搜的话,使用全局变量content记录当前陆地的面积。然后还是深搜的两种方法
1 dfs处理下一个节点,判断节点是否合法,合法则设置visited和进入下一节dfs,同时content岛屿面积 + 1
2 dfs处理当前节点,首先判断当前节点是否合法,合法的话设置visited数组,content岛屿面积 + 1,再判断周围节点
以1为例
direction = [[1, 0], [0, 1], [-1, 0], [0, -1]]
content = 0
def dfs(grid, visited, x, y):
global content
# print('v: ' + str(content) + 'x: ' + str(x) + 'y: ' + str(y))
for i in range(4):
nextx, nexty = x + direction[i][0], y + direction[i][1]
if nextx < 0 or nextx >= len(grid) or nexty < 0 or nexty >= len(grid[0]): # 越界
continue
if not visited[nextx][nexty] and grid[nextx][nexty]:
visited[nextx][nexty] = True
content += 1
dfs(grid, visited, nextx, nexty)
def main():
global content
n, m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
result = 0
visited = [[False] * m for _ in range(n)]
for x in range(n):
for y in range(m):
if not visited[x][y] and grid[x][y]:
visited[x][y] = 1
content = 1 # 陆地面积
dfs(grid, visited, x, y)
#print('v: ' + str(content))
if content > result: # 记录最大的陆地面积
result = content
print(result)
if __name__ == '__main__':
main()
广搜
还是上一题广搜的思路,使用队列进行广度优先搜索,先判断节点是否合法,再设置visited和入队。
要记录陆地面积的话,在函数中设置content,且初始化为2,广搜过程中,入队一个位置,content+1,最后返回content
from collections import deque
direction = [[1, 0], [0, 1], [-1, 0], [0, -1]]
def bfs(grid, visited, x, y):
que = deque()
que.append([x, y])
content = 1 # 记录陆地面积
while len(que) != 0:
curx, cury = que.popleft()
for i in range(4):
nextx, nexty = curx + direction[i][0], cury + direction[i][1]
if nextx < 0 or nextx >= len(grid) or nexty < 0 or nexty >= len(grid[0]): # 越界
continue
if not visited[nextx][nexty] and grid[nextx][nexty]:
visited[nextx][nexty] = True
content += 1
que.append([nextx, nexty])
return content
def main():
n, m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
result = 0
visited = [[False] * m for _ in range(n)]
for x in range(n):
for y in range(m):
if not visited[x][y] and grid[x][y]:
visited[x][y] = True
content = bfs(grid, visited, x, y)
result = max(result, content)
print(result)
if __name__ == '__main__':
main()
学习收获:
- 首先知道了在一张地图上进行广搜和深搜,然后利用广搜和深搜标记遍历过的陆地,当广搜/深搜结束后, 如果还遇到没有标记过的陆地,那么就是岛屿数量 + 1
- 而岛屿面积还是在这张地图上进行处理,在广搜和深搜的代码上改进即可;深搜(添加全局变量content记录岛屿面积),广搜(函数内添加变量content记录岛屿面积)