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

学习资料: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 !

posted @ 2024-11-21 20:24  Tristan241001  阅读(1)  评论(0编辑  收藏  举报