代码随想录算法训练营第五十二天|101.孤岛的总面积 102.沉没孤岛 103.水流问题 104.建造最大岛屿
101.孤岛的总面积
101. 孤岛的总面积
代码随想录
思路:这道题主要的难点是在于如何寻找是否是孤岛,其实思路也比较简单,就是做一个bool值来表示是否触及边缘,如果触碰到了就修改这个值,最终如果没触碰到边界,就正常返回总面积,否则就是0.
from collections import deque
directions=[[0,1],[0,-1],[1,0],[-1,0]]def main():n,m=map(int,input().split())graph=[]for i in range(n):graph.append(list(map(int,input().split())))visit=[[False]*m for _ in range(n)]result=0cnt=0def bfs(x,y):cnt=0edge=Falseque=deque([])que.append([x,y])visit[x][y]=Truewhile que:cur_x,cur_y=que.popleft()cnt+=1if cur_x==0 or cur_x==n-1 or cur_y==0 or cur_y==m-1:edge=Truefor i,j in directions:next_x=cur_x+inext_y=cur_y+jif next_x<0 or next_x>=n or next_y<0 or next_y>=m:continueif not visit[next_x][next_y] and graph[next_x][next_y]==1:visit[next_x][next_y]=Trueque.append([next_x,next_y])if edge:return 0else:return cntfor i in range(n):for j in range(m):if not visit[i][j] and graph[i][j]==1:result+=bfs(i,j)print(result)if __name__=="__main__":main()
102.沉没孤岛
102. 沉没孤岛
代码随想录
思路:这道题学到的新东西有两个,一个是用2来代表非孤岛(引入新的状态),一个是从遍历的方式,即从边界上每个点开始进行dfs或bfs,可以保证每个非孤岛都会遍历到。而在遍历修改为非孤岛状态后,再遍历一遍整个岛,所有值是1的就是孤岛
from collections import deque
directions=[[0,1],[0,-1],[1,0],[-1,0]]def dfs(graph,x,y):graph[x][y]=2for i,j in directions:next_x=x+inext_y=y+jif next_x<0 or next_x>=len(graph) or next_y<0 or next_y>=len(graph[0]):continueif graph[next_x][next_y]==1:graph[next_x][next_y]=2dfs(graph,next_x,next_y)def main():n,m=map(int,input().split())graph=[]for i in range(n):graph.append(list(map(int,input().split())))for i in range(n):if graph[i][0]==1:dfs(graph,i,0)if graph[i][m-1]==1:dfs(graph,i,m-1)for i in range(m):if graph[0][i]==1:dfs(graph,0,i)if graph[n-1][i]==1:dfs(graph,n-1,i)for i in range(n):for j in range(m):if graph[i][j]==1:graph[i][j]=0if graph[i][j]==2:graph[i][j]=1for row in graph:print(' '.join(map(str,row)))if __name__=="__main__":main()
103.水流问题
103. 高山流水
代码随想录
思路:这道题主要的创新之处也是在于遍历的方式不同,题目要求从某一个点走到边界,我们反其道而行之,从边界遍历到中间的点。遍历的过程是简单的dfs,而每个符合要求的点就填入数组。因为有两个边界,而且只有同时能到达两个边界才可以,所以选用set这种形式,可以使用&操作,来选取同时能到达两个边界的节点(要注意set中添加新节点要用add((x,y)),而不能使用[]。因为set中只能引入不变量,而[ ](即list)是可变的
directions=[[0,1],[0,-1],[1,0],[-1,0]]
first=set()
second=set()def dfs(graph,visit,x,y,side):visit[x][y]=Trueside.add((x,y))for i,j in directions:next_x=x+inext_y=y+jif next_x<0 or next_x>=len(graph) or next_y<0 or next_y>=len(graph[0]):continueif graph[next_x][next_y]>=graph[x][y] and not visit[next_x][next_y]:dfs(graph,visit,next_x,next_y,side)def main():global firstglobal secondn,m=map(int,input().split())graph=[]for i in range(n):graph.append(list(map(int,input().split())))visit=[[False]*m for _ in range(n)]for i in range(n):dfs(graph,visit,i,0,first)for i in range(m):dfs(graph,visit,0,i,first)visit=[[False]*m for _ in range(n)]for i in range(n):dfs(graph,visit,i,m-1,second)for i in range(m):dfs(graph,visit,n-1,i,second)result=first&secondfor i,j in result:print(f"{i} {j}")if __name__=="__main__":main()
104.建造最大岛屿
104. 建造最大岛屿
代码随想录
思路:这道题思路也略有抽象,需要先遍历一遍找出每个岛屿,对其编号并求出其面积,之后再遍历整个地图,找出每个为0的节点,并找出其四周若连接岛屿则加上其面积(要使用set来保证不会重复加上同一个岛屿)。每个岛屿的面积用dict来存储。实际上写的时候需要注意的细节比较多,例如第一次遍历求每个岛屿面积的时候就要求result,防止新建岛屿不能连接两个或更多岛屿
directions=[[0,1],[0,-1],[1,0],[-1,0]]
island=dict()
area=0from collections import dequedef dfs(graph,visit,x,y,cur_id):global areavisit[x][y]=Truegraph[x][y]=cur_idarea+=1for i,j in directions:nx=x+iny=y+jif nx<0 or nx>=len(graph) or ny<0 or ny>=len(graph[0]):continueif not visit[nx][ny] and graph[nx][ny]==1:dfs(graph,visit,nx,ny,cur_id)def main():n,m=map(int,input().split())graph=[]for i in range(n):graph.append(list(map(int,input().split())))visit=[[False]*m for _ in range(n)]cur_id=2result=0global areafor i in range(n):for j in range(m):if not visit[i][j] and graph[i][j]==1:area=0dfs(graph,visit,i,j,cur_id) island[cur_id]=arearesult=max(result,area)cur_id+=1for x in range(n):for y in range(m):if graph[x][y]==0:area=1seen=set()for i,j in directions:nx=x+iny=y+jif 0<=nx<n and 0<=ny<m and graph[nx][ny]>1:id_=graph[nx][ny]if id_ not in seen:area+=island[id_]seen.add(id_)result=max(result,area)print(result)if __name__=="__main__":main()