【代码随想录——图论——小岛问题】

1.水流问题

在这里插入图片描述
使用两个visited数组即可。

1.1 DFS版

package main

import "fmt"

var direction = [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}

func main() {
	var M, N int
	fmt.Scanln(&N, &M)
	sea := make([][]int, N)
	one_visited := make([][]bool, N)
	two_visited := make([][]bool, N)
	for i := 0; i < N; i++ {
		sea[i] = make([]int, M)
		one_visited[i] = make([]bool, M)
		two_visited[i] = make([]bool, M)
	}

	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			fmt.Scan(&sea[i][j])
		}
	}

	for i := 0; i < N; i++ {
		dfs(i, 0, N, M, &sea, &one_visited)
		dfs(i, M-1, N, M, &sea, &two_visited)
	}

	for j := 0; j < M; j++ {
		dfs(0, j, N, M, &sea, &one_visited)
		dfs(N-1, j, N, M, &sea, &two_visited)
	}

	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			if one_visited[i][j] && two_visited[i][j] {
				fmt.Printf("%d %d\n", i, j)
			}
		}
	}

}

func dfs(x, y, N, M int, sea *[][]int, visited *[][]bool) {
	if (*visited)[x][y] {
		return
	}
	(*visited)[x][y] = true

	for i := 0; i < 4; i++ {
		newX := x + direction[i][0]
		newY := y + direction[i][1]
		if newX < 0 || newX >= N || newY < 0 || newY >= M {
			continue
		}
		if (*sea)[newX][newY] > (*sea)[x][y] && !(*visited)[newX][newY] {
			dfs(newX, newY, N, M, sea, visited)
		}
	}
}

1.2 BFS版

package main

import "fmt"

var direction = [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}

func main() {
	var M, N int
	fmt.Scanln(&N, &M)
	sea := make([][]int, N)
	one_visited := make([][]bool, N)
	two_visited := make([][]bool, N)
	for i := 0; i < N; i++ {
		sea[i] = make([]int, M)
		one_visited[i] = make([]bool, M)
		two_visited[i] = make([]bool, M)
	}

	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			fmt.Scan(&sea[i][j])
		}
	}

	for i := 0; i < N; i++ {
		bfs(i, 0, N, M, &sea, &one_visited)
		bfs(i, M-1, N, M, &sea, &two_visited)
	}

	for j := 0; j < M; j++ {
		bfs(0, j, N, M, &sea, &one_visited)
		bfs(N-1, j, N, M, &sea, &two_visited)
	}

	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			if one_visited[i][j] && two_visited[i][j] {
				fmt.Printf("%d %d\n", i, j)
			}
		}
	}

}
func bfs(x, y, N, M int, sea *[][]int, visited *[][]bool) int {
	if (*visited)[x][y] {
		return 0
	}
	queue := make([][2]int, 0)
	queue = append(queue, [2]int{x, y})
	(*visited)[x][y] = true
	area := 0
	for len(queue) != 0 {
		pos := queue[0]
		queue = queue[1:]
		area += 1
		for i := 0; i < 4; i++ {
			newX := pos[0] + direction[i][0]
			newY := pos[1] + direction[i][1]
			if newX < 0 || newX >= N || newY < 0 || newY >= M {
				continue
			}
			if (*sea)[newX][newY] > (*sea)[pos[0]][pos[1]] && !(*visited)[newX][newY] {
				queue = append(queue, [2]int{newX, newY})
				(*visited)[newX][newY] = true
			}
		}
	}
	return area
}

2.建造最大岛屿

在这里插入图片描述

package main

import "fmt"

var direction = [][]int{{0, 1}, {0, -1}, {1, 0}, {-1, 0}}
var M, N int

func main() {

	fmt.Scanln(&N, &M)
	sea := make([][]int, N)
	visited := make([][]bool, N)
	island := make(map[int]int, 0)
	for i := 0; i < N; i++ {
		sea[i] = make([]int, M)
		visited[i] = make([]bool, M)
	}

	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			fmt.Scan(&sea[i][j])
		}
	}

	isLandIndex := 1
	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			if sea[i][j] == 1 && !visited[i][j] {
				area := 0
				dfs(i, j, isLandIndex, &sea, &visited, &area)
				island[isLandIndex] = area
				isLandIndex += 1
			}
		}
	}
	maxArea := 1
	for _, area := range island {
		if area > maxArea {
			maxArea = area
		}
	}
	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			if sea[i][j] == 0 {
				//尝试在这里建造小岛
				area := 1
				connIsland := make([]int, 0)
				for k := 0; k < 4; k++ {
					newX := i + direction[k][0]
					newY := j + direction[k][1]
					if newX < 0 || newX >= N || newY < 0 || newY >= M {
						continue
					}
					if sea[newX][newY] != 0 && !isInList(sea[newX][newY], connIsland) {
						area += island[sea[newX][newY]]
						connIsland = append(connIsland, sea[newX][newY])
					}
				}
				if area > maxArea {
					maxArea = area
				}
			}
		}
	}
	//for key, value := range island {
	//	fmt.Printf("小岛编号:%d,小岛面积:%d \n", key, value)
	//}
	fmt.Println(maxArea)
}

func isInList(isLandIndex int, isLands []int) bool {
	for i := 0; i < len(isLands); i++ {
		if isLandIndex == isLands[i] {
			return true
		}
	}
	return false
}

func dfs(x, y, seaIndex int, sea *[][]int, visited *[][]bool, area *int) {
	(*visited)[x][y] = true
	(*sea)[x][y] = seaIndex
	*area = (*area) + 1
	for i := 0; i < 4; i++ {
		newX := x + direction[i][0]
		newY := y + direction[i][1]
		if newX < 0 || newX >= N || newY < 0 || newY >= M {
			continue
		}
		if (*sea)[newX][newY] == 1 && !(*visited)[newX][newY] {
			dfs(newX, newY, seaIndex, sea, visited, area)
		}
	}
}

3.字符串接龙

在这里插入图片描述

package main

import "fmt"

var N int
var beginStr, endStr string

func main() {
	fmt.Scanln(&N)
	fmt.Scanf("%s %s", &beginStr, &endStr)
	strList := make([]string, 0)
	strMap := make(map[string]int)
	strMap[beginStr] = 0
	strMap[endStr] = 1
	strList = append(strList, beginStr)
	strList = append(strList, endStr)
	strIndex := 2
	for i := 0; i < N; i++ {
		var tempStr string
		fmt.Scanln(&tempStr)
		strMap[tempStr] = strIndex
		strList = append(strList, tempStr)
		strIndex++
	}
	if beginStr == endStr {
		fmt.Println(0)
		return
	}
	m := make([][]int, N+2)
	for i := 0; i < N+2; i++ {
		m[i] = make([]int, N+2)
	}
	for i := 0; i < N+2; i++ {
		for j := i; j < N+2; j++ {
			if canTransfer(strList[i], strList[j]) {
				m[i][j] = 1
				m[j][i] = 1
			}
		}
	}

	//printMatrix(m)
	// 开启bfs
	step := bfs(0, 1, &m)
	fmt.Println(step)
}

func canTransfer(str1, str2 string) bool {
	diff := 0
	for i := 0; i < len(str1); i++ {
		if str1[i] != str2[i] {
			diff++
		}
	}
	return diff == 1
}

func bfs(beginIndex, endIndex int, m *[][]int) int {
	queue := make([]int, 0)
	tempQueue := make([]int, 0)
	queue = append(queue, beginIndex)
	strSet := make(map[int]struct{})
	strSet[beginIndex] = struct{}{}
	step := 1
	for len(queue) != 0 {
		nowIndex := queue[0]
		if nowIndex == endIndex {
			return step
		}
		queue = queue[1:]
		for i := 0; i < N+2; i++ {
			_, ok := strSet[i]
			if ok {
				continue
			}
			if (*m)[nowIndex][i] == 1 {
				tempQueue = append(tempQueue, i)
				//表示已经在队列中
				strSet[i] = struct{}{}
			}
		}
		if len(queue) == 0 {
			for i := 0; i < len(tempQueue); i++ {
				queue = append(queue, tempQueue[i])
			}
			tempQueue = make([]int, 0)
			step++
		}
	}
	return 0
}

4.有向图的完全可达性

在这里插入图片描述

package main

import "fmt"

var directions = [4][2]int{
	{0, 1},
	{0, -1},
	{1, 0},
	{-1, 0},
}
var N, M int

func main() {
	fmt.Scanln(&N, &M)
	m := make([][]int, N+1)
	visited := make([]bool, N+1)
	for i := 0; i < N+1; i++ {
		m[i] = make([]int, N+1)
	}
	for i := 0; i < M; i++ {
		var start, end int
		fmt.Scanln(&start, &end)
		m[start][end] = 1
	}
	//bfs
	reachCount := bfs(1, &visited, &m)
	if reachCount == N {
		fmt.Println(1)
	} else {
		fmt.Println(-1)
	}
}

func bfs(start int, visited *[]bool, m *[][]int) int {
	queue := make([]int, 0)
	queue = append(queue, start)
	(*visited)[start] = true
	reachCount := 1
	for len(queue) != 0 {
		now := queue[0]
		queue = queue[1:]
		for i := 1; i < N+1; i++ {
			if !(*visited)[i] && (*m)[now][i] == 1 {
				queue = append(queue, i)
				(*visited)[i] = true
				reachCount++
			}
		}
	}
	return reachCount
}

5.岛屿的周长

在这里插入图片描述

package main

import "fmt"

var directions = [4][2]int{
	{0, 1},
	{0, -1},
	{1, 0},
	{-1, 0},
}
var N, M int

func main() {
	fmt.Scanln(&N, &M)
	m := make([][]int, N)
	for i := 0; i < N; i++ {
		m[i] = make([]int, M)
	}
	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			fmt.Scan(&m[i][j])
		}
	}
	//遍历map并向四方探索
	result := 0
	for i := 0; i < N; i++ {
		for j := 0; j < M; j++ {
			if m[i][j] == 1 {
				result += getEdgeNum(i, j, &m)
			}
		}
	}
	fmt.Println(result)
}

func getEdgeNum(x, y int, m *[][]int) int {
	edge := 4
	for i := 0; i < 4; i++ {
		newX := x + directions[i][0]
		newY := y + directions[i][1]
		if newX < 0 || newX >= N || newY < 0 || newY >= M{
			continue
		}
		if (*m)[newX][newY] == 1{
			edge--
		}
	}
	return edge
}
  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值