首页 > 编程语言 >代码随想录算法训练营第55天 | 图论岛屿+水流

代码随想录算法训练营第55天 | 图论岛屿+水流

时间:2024-07-31 21:09:10浏览次数:16  
标签:图论 55 graph 随想录 dfs range nextx nexty dir

  1. 孤岛的总面积
    https://kamacoder.com/problempage.php?pid=1173
    代码随想录
    https://www.programmercarl.com/kamacoder/0102.沉没孤岛.html
    102.沉没孤岛
    https://kamacoder.com/problempage.php?pid=1174
    代码随想录
    https://www.programmercarl.com/kamacoder/0102.沉没孤岛.html
    103.水流问题
    https://kamacoder.com/problempage.php?pid=1175
    代码随想录
    https://www.programmercarl.com/kamacoder/0103.水流问题.html
    104.建造最大岛屿
    https://www.programmercarl.com/kamacoder/0104.建造最大岛屿.html
    代码随想录
    https://www.programmercarl.com/kamacoder/0104.建造最大岛屿.html

101. 孤岛的总面积

  • 孤岛:不和边缘相连的岛屿称为孤岛

  • 将所有和边缘相连的岛屿变为平地然后统计孤岛的总面积

    深度优先搜索
    def dfs(graph,x,y):
    	direction = [[0,-1],[0,1],[1,0],[-1,0]]
    	graph[x][y] = 0
    	for dir_ in direction:
    		nextx = x+dir_[0]
    		nexty = y+dir_[1]
    		if nextx<0 or nextx>=len(graph) or nexty<0 or nexty>=len(graph[0]):
    			continue
    		if graph[nextx][nexty]==1:
    			graph[nextx][nexty]=0
    			dfs(graph,nextx,nexty)
    def main():
    	n,m = map(int,input().split())
    	graph = [[0]*m for _ in range(n)]
    	visited = [[False]*m for _ in range(n)]
    	for i in range(n):
    		data = input().split()
    		for j in range(m):
    			graph[i][j] = int(data[j])
    	# 将边界所有岛屿变为平地
    	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 j in range(m):
    		if graph[0][j]==1:
    			dfs(graph,0,j)
    		if graph[n-1][j]==1:
    			dfs(graph,n-1,j)
    	#统计剩余孤岛
    	res = 0
    	for i in range(n):
    		for j in range(m):
    			if graph[i][j]==1:
    				res+=1
    	print(res)
    if __name__ == '__main__':
    	main()
    
    广度优先搜索
    def dfs(graph,x,y):
    	direction = [[0,-1],[0,1],[1,0],[-1,0]]
    	graph[x][y] = 0
    	queue = [[x,y]]
    	while queue:
    		curr = queue.pop()
    		x = curr[0]
    		y = curr[1]
    		graph[x][y] = 0
    		for dir_ in direction:
    			nextx = x+dir_[0]
    			nexty = y+dir_[1]
    			if nextx<0 or nextx>=len(graph) or nexty<0 or nexty>=len(graph[0]):
    				continue
    			if graph[nextx][nexty]==1:
    				graph[nextx][nexty] = 0
    				queue.append([nextx,nexty])
    

102. 沉没孤岛

  • 将不是孤岛的岛变为2

  • 最后处理的:2->1 1->0 0->0

    深度优先搜索
    def dfs(graph,x,y):
    	direction = [[0,-1],[0,1],[1,0],[-1,0]]
    	graph[x][y] = 2
    	for dir_ in direction:
    		nextx = x+dir_[0]
    		nexty = y+dir_[1]
    		if nextx<0 or nextx>=len(graph) or nexty<0 or nexty>=len(graph[0]):
    			continue
    		if graph[nextx][nexty]==1:
    			graph[nextx][nexty]=2
    			dfs(graph,nextx,nexty)
    
    广度优先搜索
    
    def dfs(graph,x,y):
    	direction = [[0,-1],[0,1],[1,0],[-1,0]]
    	graph[x][y] = 0
    	queue = [[x,y]]
    	while queue:
    		curr = queue.pop()
    		x = curr[0]
    		y = curr[1]
    		graph[x][y] = 2
    		for dir_ in direction:
    			nextx = x+dir_[0]
    			nexty = y+dir_[1]
    			if nextx<0 or nextx>=len(graph) or nexty<0 or nexty>=len(graph[0]):
    				continue
    			if graph[nextx][nexty]==1:
    				graph[nextx][nexty] = 2
    				queue.append([nextx,nexty])
    
    def main():
    	n,m = map(int,input().split())
    	graph = [[0]*m for _ in range(n)]
    	visited = [[False]*m for _ in range(n)]
    
    	for i in range(n):
    		data = input().split()
    		for j in range(m):
    			graph[i][j] = int(data[j])
    	# print(graph)
    	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 j in range(m):
    		if graph[0][j]==1:
    			dfs(graph,0,j)
    		if graph[n-1][j]==1:
    			dfs(graph,n-1,j)
    
    	res = 0
    	for i in range(n):
    		for j in range(m):
    			if graph[i][j]==1:
    				graph[i][j] = 0
    			if graph[i][j] ==2:
    				graph[i][j] = 1
    
    	for i in range(n):
    		print(" ".join(map(str,graph[i])))
    
    if __name__ == '__main__':
    	main()
    

103. 水流问题

  • 从两个边界开始向上找重合点;

  • 最终把两个边界的重合点作为结果输出;

    点击查看代码
    def dfs(graph,x,y,bound_res):
    	directions = [[0,-1],[0,1],[1,0],[-1,0]]
    	if not bound_res[x][y]:
    		bound_res[x][y] = True
    	for dir_ in directions:
    		nextx = x+dir_[0]
    		nexty = y+dir_[1]
    		if nextx<0 or nextx>=len(graph) or nexty<0 or nexty>=len(graph[0]):
    			continue
    		if graph[nextx][nexty]>=graph[x][y] and not bound_res[nextx][nexty]:
    			bound_res[nextx][nexty] = True
    			dfs(graph,nextx,nexty,bound_res)
    
    def main():
    	n,m = map(int,input().split())
    	graph = [[0]*m for _ in range(n)]
    	for i in range(n):
    		data = input().split()
    		for j in range(m):
    			graph[i][j] = int(data[j])
    
    	bound_1 = [[False]*m for _ in range(n)]
    	bound_2 = [[False]*m for _ in range(n)]
    	for i in range(n):
    		dfs(graph,i,0,bound_1)
    		dfs(graph,i,m-1,bound_2)
    	for j in range(m):
    		dfs(graph,0,j,bound_1)
    		dfs(graph,n-1,j,bound_2)
    	for i in range(n):
    		for j in range(m):
    			if bound_1[i][j] and bound_2[i][j]:
    				print(" ".join([str(i),str(j)]))
    
    if __name__ == '__main__':
    	main()
    

104.建造最大岛屿

  • 首先分别标记不同岛屿的大小、修改graph上岛屿为index;
  • 分别统计水变成陆地后附近岛屿大小和;
点击查看代码
def dfs(graph,visited,x,y,mark,count):
    directions = [[0,-1],[0,1],[1,0],[-1,0]]
    for dir_ in directions:
        nextx = x+dir_[0]
        nexty = y+dir_[1]
        if nextx<0 or nextx>=len(graph) or nexty<0 or nexty>= len(graph[0]):
            continue
        if graph[nextx][nexty]==1 and visited[nextx][nexty]==0:
            count = count+1
            visited[nextx][nexty] = 1
            graph[nextx][nexty] = mark
            count = dfs(graph,visited,nextx,nexty,mark,count)
    return count
    

def main():
    n,m = map(int,input().split())
    graph = [[0]*m for _ in range(n)]
    for i in range(n):
        data = input().split()
        for j in range(m):
            graph[i][j] = int(data[j])

    visited = [[0]*m for _ in range(n)]
    map_ = {}
    isgrid = True
    mark = 2
    for i in range(n):
        for j in range(m):
            if graph[i][j] == 0:
                isgrid = False
            if visited[i][j]==0 and graph[i][j]==1:
                count = 1
                visited[i][j] = 1
                graph[i][j] = mark
                count = dfs(graph,visited,i,j,mark,count)
                map_[mark] = count
                mark = mark+1
    # print(graph)
    if isgrid:
        print(str(n*m))
        return
    directions = [[0,-1],[0,1],[1,0],[-1,0]]
    res = 0
    # visited_grid = []
    for i in range(n):
        for j in range(m):
            count = 1
            visited_grid = []
            if graph[i][j]==0:
                for dir_ in directions:
                    nextx = i+dir_[0]
                    nexty = j+dir_[1]
                    if nextx<0 or nextx>=len(graph) or nexty<0 or nexty>= len(graph[0]):
                        continue
                    if graph[nextx][nexty] in visited_grid:
                        continue
                    if graph[nextx][nexty]>0:
                        count+= map_[graph[nextx][nexty]]
                    visited_grid.append(graph[nextx][nexty])
            res = max(res,count)
    print(str(res))
if __name__ == '__main__':
    main()

标签:图论,55,graph,随想录,dfs,range,nextx,nexty,dir
From: https://www.cnblogs.com/P201821440041/p/18335476

相关文章

  • CF455D Serega and Fun 题解
    Beforeit来当一回教练的题解翻译家,平衡树这种高级算法自然是不会的,所以详细讲一下STL。成为蒟蒻(也就是自己)的福音。Solution我们观察到题目要求“把第\(r\)个数插入在第\(l\)个数之前,其他数顺序不变“,使用\(deque\)的\(push\)_\(front\)和\(push\)_$back$操作可......
  • 代码随想录 day 41 买卖股票的最佳时机系列
    买卖股票的最佳时机买卖股票的最佳时机解题思路使用动态规划的思路解决,这类题目和之前做到过的所有动态规划相比有一定变化。在确定数组方面,这系列的题目都使用了二维数组来表示买卖股票的不同状态。在递归方面,本系列和小偷,背包等问题不同,它的状态递推关系也不是需要前两种系列......
  • 代码随想录训练第三十天|01背包理论基础、01背包、LeetCode416.分割等和子集
    文章目录01背包理论基础01背包二维dp数组01背包一维dp数组(滚动数组)416.分割等和子集思路01背包理论基础背包问题的理论基础重中之重是01背包,一定要理解透!leetcode上没有纯01背包的问题,都是01背包应用方面的题目,也就是需要转化为01背包问题。所以我先通过纯01背......
  • 代码随想录训练第三十一天|LeetCode1049.最后一块石头的重量II、LeetCode494.目标和、
    文章目录1049.最后一块石头的重量II思路一维数组二维数组494.目标和思路一维数组解法二维数组解法474.一和零思路1049.最后一块石头的重量II有一堆石头,用整数数组stones表示。其中stones[i]表示第i块石头的重量。每一回合,从中选出任意两块石头,然后将它们一......
  • 代码随想录训练第三十二天|完全背包理论基础、LeetCode518.零钱兑换II、LeetCode377.
    文章目录完全背包理论基础完全背包总结518.零钱兑换II思路一维数组二维数组377.组合总和Ⅳ思路卡码网70.爬楼梯(进阶版)思路完全背包理论基础完全背包有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i]。每件物品都有无......
  • 代码随想录训练第三十三天|LeetCode322. 零钱兑换、LeetCode279.完全平方数、LeetCode
    文章目录322.零钱兑换思路279.完全平方数思路139.单词拆分思路多重背包背包总结遍历顺序01背包完全背包总结322.零钱兑换给你一个整数数组coins,表示不同面额的硬币;以及一个整数amount,表示总金额。计算并返回可以凑成总金额所需的最少的硬币个数。如果......
  • 智能座舱背后主流车机平台(SA8155/SA8295)的高通Hexagon DSP是什么?
    智能座舱背后主流车机平台(SA8155/SA8295)的高通HexagonDSP是什么?一、高通HexagonDSP的辉煌发展历程高通,作为全球领先的无线通信技术创新者,其处理器技术一直走在行业前列。随着智能手机和物联网设备的普及,对处理器性能的要求日益提升,尤其是在AI和机器学习领域。高通Hex......
  • 第五十六天 第十一章:图论part06 108.冗余连接 109. 冗余连接II
    108.冗余连接继续使用查并集的方法,如果两个元素是在一个集合,那么我们就输出,反之加入集合。#include<iostream>#include<vector>usingnamespacestd;intN;vector<int>father=vector<int>(1001,0);voidinit(){for(inti=0;i<=N;i++){father[i]=i;......
  • 代码随想录算法训练营第53天 | 图论2:岛屿数量相关问题
    99.岛屿数量https://kamacoder.com/problempage.php?pid=1171岛屿深搜https://www.programmercarl.com/kamacoder/0099.岛屿的数量深搜.html岛屿广搜https://www.programmercarl.com/kamacoder/0099.岛屿的数量广搜.html#思路100.岛屿的最大面积https://www.programmercar......
  • 代码随想录 day40 打家劫舍 及其变体
    打家劫舍打家劫舍解题思路动态规划解决问题,通过前两个值决定第三个值,需要注意的是初始值的选择,第二个的值是取前两个数中较大的,这样是为了保证跳过不需要取的值知识点动态规划心得初始值的选择没有考虑到,其余的都写出来了打家劫舍二打家劫舍二解题思路前一题的改进,只......