101. 孤岛的总面积
dfs:两种写法:一种是进来之前就判断了,判断条件在dfs的for内部;另一种是进来没有判断,那么终止条件在dfs开头。
不管哪一种写法,主函数里的判断都不能少
python
# dfs
directions = [[0,1],[1,0],[0,-1],[-1,0]]
area = 0
def dfs(grid, x, y):
global area
area += 1
grid[x][y] = 0
# surrounding area
for i in range(4):
next_x = x + directions[i][0]
next_y = y + directions[i][1]
if next_x < 0 or next_x >=n or next_y < 0 or next_y >=m:
continue
if grid[next_x][next_y] == 1:
dfs(grid, next_x, next_y)
if __name__ == "__main__":
n,m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
# n,m = 4,5
# grid = [[1,1,0,0,0],[1,1,0,0,0],[0,0,1,0,0],[0,0,0,1,1]]
for j in range(m):
if grid[0][j] == 1:
dfs(grid, 0, j)
if grid[-1][j] == 1:
dfs(grid, n-1, j)
for i in range(n):
if grid[i][0] == 1:
dfs(grid, i, 0)
if grid[i][-1] == 1:
dfs(grid, i, m-1)
area = 0
for i in range(1, n-1):
for j in range(1, m-1):
if grid[i][j] == 1:
area += 1
# dfs(grid, i, j)
print(area)
bfs: 加进来的时候就变,不要等pop的时候再变。即两处append的地方,开头和for内部,都要同时加变化。
python
# bfs
from collections import deque
directions = [[0,1],[1,0],[0,-1],[-1,0]]
area = 0
def bfs(grid, x, y):
global area
que = deque()
que.append([x,y])
# area += 1
grid[x][y] = 0
while que:
cur_x, cur_y = que.popleft()
for i in range(4):
next_x = cur_x + directions[i][0]
next_y = cur_y + directions[i][1]
if next_x < 0 or next_x >= n or next_y < 0 or next_y >=m:
continue
if grid[next_x][next_y] == 1:
que.append([next_x, next_y])
# area += 1
grid[next_x][next_y] = 0
if __name__ == "__main__":
n,m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
# n,m = 4,5
# grid = [[1,1,0,0,0],[1,1,0,0,0],[0,0,1,0,0],[0,0,0,1,1]]
for j in range(m):
if grid[0][j] == 1:
bfs(grid, 0, j)
if grid[-1][j] == 1:
bfs(grid, n-1, j)
for i in range(n):
if grid[i][0] == 1:
bfs(grid, i, 0)
if grid[i][-1] == 1:
bfs(grid, i, m-1)
area = 0
for i in range(1, n-1):
for j in range(1, m-1):
if grid[i][j] == 1:
area += 1
# dfs(grid, i, j)
print(area)
102. 沉没孤岛
空间复杂度高了,可以不用新建一个list,而是把陆地改成2,以示区分,然后遍历,再把孤岛改成0,陆地改成1
dfs: 进入条件即退出条件,二者选一即可
python
# DFS
dire = [[0,1],[1,0],[0,-1],[-1,0]]
def dfs(grid, x, y):
grid[x][y] = 0
for i in range(4):
next_x = x + dire[i][0]
next_y = y + dire[i][1]
if next_x < 0 or next_x >= n or next_y < 0 or next_y >= m:
continue
if grid[next_x][next_y] == 1:
dfs(grid, next_x, next_y)
if __name__ == "__main__":
n,m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
# deepcopy instead of shallow copy
grid_2 = [nested[:] for nested in grid]
# erase mainland
for i in range(n):
if grid[i][0] == 1:
dfs(grid, i, 0)
if grid[i][-1] == 1:
dfs(grid, i, m-1)
for j in range(m):
if grid[0][j] == 1:
dfs(grid, 0, j)
if grid[-1][j] == 1:
dfs(grid, n-1, j)
# mainland = all - isolated islands
for i in range(n):
for j in range(m):
grid[i][j] = grid_2[i][j] - grid[i][j]
# output
for i in range(n):
print(" ".join(map(str, grid[i])))
bfs
python
# DFS
from collections import deque
dire = [[0,1],[1,0],[0,-1],[-1,0]]
def bfs(grid, x, y):
que = deque()
que.append([x,y])
grid[x][y] = 0
while que:
cur_x, cur_y = que.popleft()
for i in range(4):
next_x = cur_x + dire[i][0]
next_y = cur_y + dire[i][1]
if next_x < 0 or next_x >= n or next_y < 0 or next_y >= m:
continue
if grid[next_x][next_y] == 1:
que.append([next_x, next_y])
grid[next_x][next_y] = 0
if __name__ == "__main__":
n,m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
# deepcopy instead of shallow copy
grid_2 = [nested[:] for nested in grid]
for i in range(n):
if grid[i][0] == 1:
bfs(grid, i, 0)
if grid[i][-1] == 1:
bfs(grid, i, m-1)
for j in range(m):
if grid[0][j] == 1:
bfs(grid, 0, j)
if grid[-1][j] == 1:
bfs(grid, n-1, j)
for i in range(n):
for j in range(m):
grid[i][j] = grid_2[i][j] - grid[i][j]
for i in range(n):
print(" ".join(map(str, grid[i])))
103.水流问题
dfs, bfs流程都差不多,主要看在图的处理上,怎么需要dfs,bfs
dfs:
python
# DFS
# from collections import deque
dire = [[0,1],[-1,0],[1,0],[0,-1]] #上,左,右,下
# first = False
# second = False
def dfs(grid, visited, x, y):
# 从(x,y)出发,看水流能逆流到哪里去
# 即顺流的逆运算
# 因为顺流的起始点太多,是整个矩阵,
# 但逆流只有边界,所以从边界出发,进行逆运算,判断哪里能逆流上去,复杂度比较简单
visited[x][y] = True
for i in range(4):
next_x = x + dire[i][0]
next_y = y + dire[i][1]
if next_x < 0 or next_x >= n or next_y < 0 or next_y >= m:
continue
if grid[next_x][next_y] >= grid[x][y] and not visited[next_x][next_y]:
# not visited 条件不可少,这里用flowable更准确
# 看边界能否逆流到这里, (next_x. next_y)
# and 前后顺序可以颠倒,因为我只看这个格子能不能从边界逆流而上,
# 不看从哪里逆流而上
# 在第一/第二边界分开时,不用管从哪里流过来
dfs(grid, visited, next_x, next_y)
if __name__ == "__main__":
n,m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
first = [[False]*m for _ in range(n)]
second = [[False]*m for _ in range(n)]
# visited = [[False]*m for _ in range(n)]
for i in range(n):
dfs(grid, first, i, 0)
dfs(grid, second, i, m-1)
for j in range(m):
dfs(grid, first, 0, j)
dfs(grid, second, n-1, j)
for i in range(n):
for j in range(m):
if first[i][j] and second[i][j]:
print(f"{i} {j}")
bfs:
python
# BFS
from collections import deque
dire = [[0,1],[-1,0],[1,0],[0,-1]] #上,左,右,下
# first = False
# second = False
def bfs(grid, visited, x, y):
que = deque()
que.append([x,y])
visited[x][y] = True
# print(f"({x}{y})")
while que:
cur_x, cur_y = que.popleft()
for i in range(4):
next_x = cur_x + dire[i][0]
next_y = cur_y + dire[i][1]
if next_x < 0 or next_x >= n or next_y < 0 or next_y >= m:
continue
if grid[next_x][next_y] >= grid[cur_x][cur_y] and not visited[next_x][next_y]:
que.append([next_x, next_y])
visited[next_x][next_y] = True
if __name__ == "__main__":
n,m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
# n, m = 5,5
# grid = [[1,3,1,2,4],
# [1,2,1,3,2],
# [2,4,7,2,1],
# [4,5,6,1,1],
# [1,4,1,2,1]]
first = [[False]*m for _ in range(n)]
second = [[False]*m for _ in range(n)]
for i in range(n):
bfs(grid, first, i, 0)
bfs(grid, second, i, m-1)
for j in range(m):
bfs(grid, first, 0, j)
bfs(grid, second, n-1, j)
for i in range(n):
for j in range(m):
if first[i][j] and second[i][j]:
print(f"{i} {j}")
104.建造最大岛屿
dfs
python
# DFS
# from collections import deque
from collections import defaultdict
dire = [[0,1],[-1,0],[1,0],[0,-1]] #上,左,右,下
count = 0
def dfs(grid, x, y, mark):
if grid[x][y] != 1:
return
global count
grid[x][y] = mark
count += 1
for i in range(4):
next_x = x + dire[i][0]
next_y = y + dire[i][1]
if next_x < 0 or next_x >= n or next_y < 0 or next_y >= m:
continue
dfs(grid, next_x, next_y, mark)
if __name__ == "__main__":
n,m = map(int, input().split())
grid = []
for _ in range(n):
grid.append(list(map(int, input().split())))
# n,m = 4,5
# grid = [[1,1,0,0,0],
# [1,1,0,0,0],
# [0,0,1,0,0],
# [0,0,0,1,1]]
grid_num = defaultdict(int)
mark = 2
ocean_flag = False
for i in range(n):
for j in range(m):
if grid[i][j] == 1:
count = 0
dfs(grid, i, j, mark)
grid_num[mark] = count
mark += 1
continue
if grid[i][j] == 0:
ocean_flag = True
result = 0
area = 0
if ocean_flag == False:
for key in grid_num.keys():
result += grid_num[key]
else:
for i in range(n):
for j in range(m):
if grid[i][j] == 0:
area = 1
added_grid = set()
for k in range(4):
new_x = i + dire[k][0]
new_y = j + dire[k][1]
if new_x < 0 or new_x >= n or new_y < 0 or new_y >= m:
continue
if grid[new_x][new_y] != 0 and grid[new_x][new_y] not in added_grid:
added_grid.add(grid[new_x][new_y])
area += grid_num[grid[new_x][new_y]]
# print(f"({new_x},{new_y}) {area}")
# print(f"{area}")
result = max(result, area)
print(result)
bfs
python
from collections import deque
from collections import defaultdict
dire = [[0,1],[-1,0],[1,0],[0,-1]] #上,左,右,下
count = 0
def bfs(grid, x, y, mark):
global count
que = deque()
que.append([x,y])
grid[x][y] = mark
count += 1
while que:
cur_x, cur_y = que.popleft()
for i in range(4):
next_x = cur_x + dire[i][0]
next_y = cur_y + dire[i][1]
if next_x < 0 or next_x >= n or next_y < 0 or next_y >= m:
continue
if grid[next_x][next_y] == 1:
que.append([next_x,next_y])
grid[next_x][next_y] = mark
count += 1