首页 > 编程语言 >代码随想录算法训练营day52 day53| 卡码网101.孤岛的总面积 102.沉没孤岛 103.水流问题 104.建造最大岛屿 110.字符串接龙 105.有向图的完全可达性

代码随想录算法训练营day52 day53| 卡码网101.孤岛的总面积 102.沉没孤岛 103.水流问题 104.建造最大岛屿 110.字符串接龙 105.有向图的完全可达性

时间:2024-11-21 20:32:39浏览次数:1  
标签:cur grids 岛屿 随想录 dfs range 孤岛 input visited

学习资料:https://www.programmercarl.com/kamacoder/0101.孤岛的总面积.html#思路

邻接矩阵是否被遍历过;每个坐标点上的值为0、1、2等等;四个边的考虑;地图的遍历次数
都是卡码网的题

学习记录:
101.孤岛的总面积

点击查看代码
# 用深搜,遍历邻接矩阵的四个边,先遍历所有可遍历的岛屿,把这些遍历到的陆地变成海洋
# 那么后续如果还有未遍历的岛就肯定是孤岛
directions = [[1,0],[-1,0],[0,1],[0,-1]]
result = 0

def dfs(grids, x, y):
    grids[x][y] = 0 # 本题将边界处岛屿都变成海洋
    global result
    result += 1
    
    for i,j in directions:
        cur_x = x+i
        cur_y = y+j
        # 若索引超出边界就终止
        if cur_x<0 or cur_x>=len(grids) or cur_y<0 or cur_y>=len(grids[0]):
            continue
        if not visited[cur_x][cur_y] and grids[cur_x][cur_y]==1:
            visited[cur_x][cur_y]=True
            dfs(grids, cur_x, cur_y)
    

# 读取输入值
n,m = map(int, input().split())
grids=[]
for i in range(n):
    grids.append(list(map(int, input().split())))
# 构造visited
visited = [[False]*m for _ in range(n)]

# 处理边界值
for i in range(m):
    if grids[0][i]==1 and not visited[0][i]:
        visited[0][i]=True
        dfs(grids,0,i)
    # 下边界
    if grids[n-1][i]==1 and not visited[n-1][i]:
        visited[n-1][i]=True
        dfs(grids,n-1,i)

# 处理左右边界
for j in range(n):
    if grids[j][0]==1 and not visited[j][0]:
        visited[j][0]=True
        dfs(grids,j, 0)
    if grids[j][m-1]==1 and not visited[j][m-1]:
        visited[j][m-1]=True
        dfs(grids,j, m-1)

# 计算孤岛面积
result = 0  # 重新对result初始化,避免遍历边界岛屿时的累加值
for i in range(n):
    for j in range(m):
        if grids[i][j]==1 and not visited[i][j]:
            visited[i][j]=True
            dfs(grids, i, j)
print(result)


102.沉没孤岛

点击查看代码
# 深搜;邻接矩阵;解法:把边界岛屿变为2,剩下的1都是孤岛的,就好辨别了
# 这道题不用visited
directions=[[1,0],[-1,0],[0,1],[0,-1]]

def dfs(grids,x,y):
    grids[x][y]=2
    for i,j in directions:
        cur_x = x+i
        cur_y = y+j
        # 终止条件,超过边界
        if cur_x<0 or cur_x>=len(grids) or cur_y<0 or cur_y>=len(grids[0]):
            continue
        # 陆地
        if grids[cur_x][cur_y]==1:
            dfs(grids,cur_x,cur_y)

# 导入输入值
n,m = map(int, input().split())
grids = []
for i in range(n):
    grids.append(list(map(int, input().split())))

# 遍历左右边
for i in range(n):
    if grids[i][0]==1:
        dfs(grids, i, 0)
    if grids[i][m-1]==1:
        dfs(grids, i, m-1)
# 遍历上下边
for j in range(m):
    if grids[0][j]==1:
        dfs(grids,0,j)
    if grids[n-1][j]==1:
        dfs(grids,n-1,j)

# 现在边界岛屿值都变成2了,那重新遍历,遇到2为边缘岛屿,遇到1为孤岛
for i in range(n):
    for j in range(m):
        if grids[i][j]==2:   # 周边岛变回陆地
            grids[i][j]=1
        elif grids[i][j]==1:
            grids[i][j]=0   # 孤岛变成海洋
            
for row in grids:
    print(' '.join(map(str, row)))   # 打印邻接矩阵

103.水流问题(说实话真没看懂题解,总感觉是水从高向低流)

点击查看代码
first = set()
second = set()
directions = [[1,0],[-1,0],[0,1],[0,-1]]

def dfs(i,j,grids,visited,side):
    if visited[i][j]:
        return
    
    visited[i][j] = True
    side.add((i,j))
    
    for x,y in directions:
        cur_x = i+x
        cur_y = j+y
        if (
            0<=cur_x<len(grids)
            and 0<=cur_y<len(grids[0])
            and int(grids[cur_x][cur_y]>=int(grids[i][j])) # 怎么感觉是从低向高流呢?
            ):
                dfs(cur_x, cur_y, grids, visited, side)


# 导入输入值
n,m = map(int, input().split())
# 构造邻接矩阵
grids=[]
for i in range(n):
    grids.append(list(map(int, input().split())))

# 是否可达第一边界
visited = [[False]*m for _ in range(n)]
for i in range(m):
    dfs(0, i, grids, visited, first)
for i in range(n):
    dfs(i, 0, grids, visited, first)

# 是否可达第二边界
visited = [[False]*m for _ in range(n)]
for i in range(m):
    dfs(n-1, i, grids, visited, second)
for i in range(n):
    dfs(i, m-1, grids, visited, second)

res = first & second
for x,y in res:
    print(f"{x} {y}")

104.建造最大岛屿

点击查看代码
# 本题思路:统计每个岛屿的面积,从2开始(避开0,1)给岛屿编号[mark,area];深搜;邻接矩阵
# 因为每个点都mark了,所以当值不为0也不为1时,代表以及访问过了,本题不用visited

import collections

directions = [[1,0],[-1,0],[0,1],[0,-1]]
count = 0

def dfs(grids,mark,x,y):
    global count

    # 终止条件,遇到海水或者已访问过的
    if grids[x][y] == 0 or grids[x][y] != 1:   # 因为
        return
    grids[x][y] = mark
    count += 1
    
    for i,j in directions:
        next_x = x+i
        next_y = y+j
        if (
            0<=next_x<len(grids)
            and 0<=next_y<len(grids[0])
            and grids[next_x][next_y] == 1
            ):
                dfs(grids,mark,next_x,next_y)
        # if next_x<0 or next_x>=len(grids) or next_y<0 or next_y>=len(grids[0]):
        #     continue
        # dfs(grids,mark,next_x,next_y)   # 不用判断是否遍历过,因为前面已经给出遍历条件

# 导入输入值
n,m = map(int, input().split())
grid = []
for i in range(n):
    grid.append(list(map(int, input().split())))



# 记录岛屿标记
gridNum = {}
mark=2

# # 判断是否整个矩阵都是陆地
# isAllgrid = True

# 第一次遍历地图:统计每个岛屿的面积
for i in range(n):
    for j in range(m):
        if grid[i][j]==1:
            count = 0
            dfs(grid,mark,i,j)
            gridNum[mark]=count
            mark += 1

# print(gridNum)
res = 0
# 第二次遍历地图:把每个海洋都变成陆地试一次
for i in range(n):
    for j in range(m):
        if grid[i][j]==0:
            max_island = 1
            v = set()
            for x,y in directions:
                next_x = x+i
                next_y = y+j
                if (
                    0<=next_x<len(grid) and 0<=next_y<len(grid[0])
                    and grid[next_x][next_y] != 0
                    and grid[next_x][next_y] not in v     # 避免重复
                ):
                    max_island += gridNum[grid[next_x][next_y]]
                    v.add(grid[next_x][next_y])
            res = max(res, max_island)

if res == 0: # 无水,全是陆地
    print(max(gridNum.values()))
else:
    print(res)

110.字符串接龙(广搜)

点击查看代码
# 无向图;广搜;如果能到尾巴,一定是最短距离;如果两个字符串有两个字母一样,则两者间有连线

def judge(s1, s2):
    """???判断两个字符串有没有连线,即两者需要有两个一样的字母"""
    count = 0
    for i in range(len(s1)):
        if s1[i] != s2[i]:
            count += 1
    return count==1
    

# 导入输入值
n = map(int, input())
beginstr, endstr = input().split()

# 如果首尾一样,则直接连线,得最短路径
if beginstr == endstr:
    print(0)
else:
    # 导入剩下的输入值
    strlist = []
    for i in range(n):
        strlist.append(input())
        
    # 使用广搜
    visited = [False for _ in range(n)]
    # 构造一个队列
    queue = [[beginstr, 1]]  # 存字符串和路径长度
    while queue:
        str, step = queue.pop(0)
        if judge(str,endstr):
            print(step+1)
        else:
            for i in range(n):
                if visited[i]==False and judge(strlist[i], str):
                    visited[i] = True
                    queue.append([strlist[i], step+1])
    print(0)
    

105.有向图的完全可达性(抄的,没看懂)

点击查看代码
def dfs(grids, key, visited):
    for neighbor in grids[key]:
        if not visited[neighbor]:
            visited[neighbor] = True
            dfs(grids, neighbor, visited)
            
# 输入值
n,k = map(int, input().split())
grids = [[] for _ in range(n+1)]

for _ in range(k):
    s, t = map(int, input().split())
    grids[s].append(t)

visited = [False]*(n+1)
visited[1] = True
dfs(grids,1,visited)

index = 0
for i in range(1, n+1):
    if not visited[i]:
        print(-1)
        index = 1
        break
if index == 0:
    print(1)
    

106.岛屿的最大周长(非广搜或者深搜)

点击查看代码
# 解法二:陆地数*4-相邻陆地数*2=边长

# 输入值
n,m = map(int, input().split())
grid = []
for i in range(n):
    grid.append(list(map(int, input().split())))

# 初始化陆地数和相邻陆地数
sum_land = 0
cross = 0

for i in range(n):
    for j in range(m):
        if grid[i][j] == 1:
            sum_land += 1
            if i-1 >= 0 and grid[i-1][j]==1:  # 上边相邻路径
                cross += 1
            if j-1>=0 and grid[i][j-1] == 1:  # 左边相邻路径
                cross += 1

result = sum_land*4 - cross*2
print(result)


PS:好难哦,要学不下去了,失去了所有力气和精神,好难好难
今天继续晴天,晒太阳真舒服
昨天今天都吃了超多好吃的,糍粑辣椒干锅鸡、螺蛳粉、各种砂锅米线、番茄圆子汤、青提奶油蛋糕、豪华煮泡面,爽得很~
倒计时 8 !

标签:cur,grids,岛屿,随想录,dfs,range,孤岛,input,visited
From: https://www.cnblogs.com/tristan241001/p/18561456

相关文章

  • 代码随想录——二叉树19.最大二叉树
    递归最容易想到,采用先序遍历。1.遍历数组,找出当前区间的最大值;2.使用该最大值作为根节点;3.对数组的左半部分和右半部分递归调用构建最大二叉树。这种方式是标准的分治法,每次递归都需要遍历当前区间,找到最大值。因此,时间复杂度是O(n^2),因为每一层递归都会遍历一遍数组,且递......
  • 代码随想录算法训练营第八天|344.反转字符串、541.反转字符串||、卡玛网54.替换数字
    344和541来自leetcode,54来自卡玛网344.反转字符串很简单的一道题,直接把数组一分为二,第一个和最后一个互换就行,直到遍历到数组一半,就结束了,从第一个往后就是s[i],最后一个往前就是s[s.lenght-i-1]。publicclassSolution{publicvoidreverseString(char[]s){......
  • 代码随想录:链表相交
    代码随想录:链表相交像做数学题一样,要挖掘出表象下的实际条件。比如这道题,链表在一段时间后相交,其实含义是两者的尾部是相同的,所以只需要将尾部对齐即可。/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListN......
  • 代码随想录:删除链表的倒数第N个节点
    代码随想录:删除链表的倒数第N个节点链表题目如果想找当前节点的前n个节点的话,用双指针法。另外务必用虚头节点。/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*......
  • 代码随想录:两两交换链表中的节点
    代码随想录:两两交换链表中的节点链表题目务必用虚头节点,很多问题会变简单很多/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*ListNode(intx):val(x),next(......
  • 代码随想录算法训练营day51| 卡码网99.岛屿数量 卡码网100.岛屿的最大面积
    学习资料:https://www.programmercarl.com/kamacoder/0099.岛屿的数量深搜.html#思路深度优先搜索和广度优先搜索今天用的邻接矩阵学习记录:卡码网99.岛屿数量(深搜or广搜;用一个自己设计的二维矩阵来控制节点的移动方向:上下左右)点击查看代码fromcollectionsimportdequedi......
  • 代码随想录:移除链表元素
    代码随想录:移除链表元素简单的链表操作,注意C++中在访问一个实体结构体时,用.来进行元素访问ListNodehead;head.val=10;head.next=nullptr;在访问一个指针变量时,用→来进行元素访问,如在本题中,题目给的head是一个指针,所以所有的变量访问都用→/***Definitionforsing......
  • 代码随想录:设计链表
    代码随想录:设计链表这题遇到的问题是,在private中声明后,在构造函数中初始化的时候又声明了一次,大类的构造函数和结构体的构造函数弄晕掉了。另外虚头节点是真好用,以后记得用。一开始写成了这样:classMyLinkedList{public:structLinkNode{intvalue;......
  • 代码随想录算法训练营第七天(LeetCode454.四数相加Ⅱ;LeetCode383.赎金信;LeetCode15.三
    LeetCode454.四数相加Ⅱ题目链接:四数相加Ⅱ题目链接思路这道题目给定我们四个数组,让我们判断从四个数组中分别取一个元素,然后将这四个元素相加,值为0的元组个数,所以我们可以模仿两数之和,因为四个数组中分别取元素就是任意取,不需要考虑去重的问题,所以可以将四个数组转......
  • 代码随想录算法训练营第八天(LeetCode344.反转字符串;LeetCode541.反转字符串Ⅱ;卡码网54
    LeetCode344.反转字符串题目链接:反转字符串题目链接思路这道题目让我们进行字符串的反转,其实直接使用reverse相关的函数就可以解决问题。但是解决问题的时候,如果这道题目使用库函数就可以直接解决,就最好不要使用库函数;如果库函数只是题目中解法的一小步,那么就使用......