Skip to content

go版本解法:完全背包理论基础-二维DP数组、多重背包理论基础、水流问题(改正暴力解法,添加优化解法)建造最大岛屿、最小生成树(两种算法)、冗余连接。 #2884

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
73 changes: 72 additions & 1 deletion problems/kamacoder/0053.寻宝-Kruskal.md
Original file line number Diff line number Diff line change
@@ -542,9 +542,80 @@ if __name__ == "__main__":

```


### Go

```go
package main

import (
"bufio"
"fmt"
"os"
"strconv"
"sort"
"strings"
)

var father [10001]int

func init() {
for i := 0; i < 10001; i++ {
father[i] = i
}
}

func find(u int) int {
if father[u] == u {
return u
}
father[u] = find(father[u])
return father[u]
}

func join(u, v int) {
u = find(u)
v = find(v)
if u != v {
father[v] = u
}
}

func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
input := strings.Fields(scanner.Text())
//v, _ := strconv.Atoi(input[0])
e, _ := strconv.Atoi(input[1])

edges := make([][3]int, e)
for i := 0; i < e; i++ {
scanner.Scan()
input = strings.Fields(scanner.Text())
x, _ := strconv.Atoi(input[0])
y, _ := strconv.Atoi(input[1])
k, _ := strconv.Atoi(input[2])
edges[i] = [3]int{x, y, k}
}

sort.Slice(edges, func(i, j int) bool {
return edges[i][2] < edges[j][2]
})

result := 0
for _, edge := range edges {
u, v, w := edge[0], edge[1], edge[2]
if find(u) != find(v) {
result += w
join(u, v)
}
}

fmt.Println(result)
}
```



### Rust

### JavaScript
78 changes: 78 additions & 0 deletions problems/kamacoder/0053.寻宝-prim.md
Original file line number Diff line number Diff line change
@@ -690,6 +690,84 @@ if __name__ == "__main__":

### Go

```go
package main

import (
"bufio"
"fmt"
"math"
"os"
"strconv"
"strings"
)

func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
input := strings.Fields(scanner.Text())
v, _ := strconv.Atoi(input[0])
e, _ := strconv.Atoi(input[1])

// 初始化图,边权值默认为无穷大(题目中权值最大为10000)
grid := make([][]int, v+1)
for i := range grid {
grid[i] = make([]int, v+1)
for j := range grid[i] {
grid[i][j] = 10001
}
}

// 输入边信息
for e > 0 {
scanner.Scan()
input = strings.Fields(scanner.Text())
x, _ := strconv.Atoi(input[0])
y, _ := strconv.Atoi(input[1])
k, _ := strconv.Atoi(input[2])
grid[x][y] = k
grid[y][x] = k
e--
}

// Prim算法
minDist := make([]int, v+1) // 节点到生成树的最小距离
isInTree := make([]bool, v+1) // 节点是否在生成树中
for i := range minDist {
minDist[i] = 10001
}
minDist[1] = 0 // 从节点1开始

result := 0
for i := 1; i <= v; i++ {
// 1. 选择距离生成树最近的节点
cur := -1
minVal := math.MaxInt32
for j := 1; j <= v; j++ {
if !isInTree[j] && minDist[j] < minVal {
minVal = minDist[j]
cur = j
}
}

// 2. 将该节点加入生成树
isInTree[cur] = true
result += minDist[cur]

// 3. 更新非生成树节点到生成树的距离
for j := 1; j <= v; j++ {
if !isInTree[j] && grid[cur][j] < minDist[j] {
minDist[j] = grid[cur][j]
}
}
}

fmt.Println(result)
}
```



### Rust

### JavaScript
144 changes: 122 additions & 22 deletions problems/kamacoder/0103.水流问题.md
Original file line number Diff line number Diff line change
@@ -413,6 +413,9 @@ if __name__ == "__main__":
```

### Go

暴力解法

```go
package main

@@ -424,71 +427,168 @@ import (
"bufio"
)

var directions = [][]int{{0, -1}, {0, 1}, {-1, 0}, {1, 0}} // 四个方向的偏移量
var directions = [][]int{{0, -1}, {0, 1}, {-1, 0}, {1, 0}}

func main() {
scanner := bufio.NewScanner(os.Stdin)

scanner.Scan()
lineList := strings.Fields(scanner.Text())
N, _ := strconv.Atoi(lineList[0])
M, _ := strconv.Atoi(lineList[1])

grid := make([][]int, N)
visited := make([][]bool, N) // 用于标记是否访问过
visited := make([][]bool, N)
for i := 0; i < N; i++ {
grid[i] = make([]int, M)
visited[i] = make([]bool, M)
scanner.Scan()
lineList = strings.Fields(scanner.Text())

for j := 0; j < M; j++ {
grid[i][j], _ = strconv.Atoi(lineList[j])
}
}

// 遍历每个单元格,使用DFS检查是否可达两组边界

for i := 0; i < N; i++ {
for j := 0; j < M; j++ {
canReachFirst, canReachSecond := dfs(grid, visited, i, j)
if canReachFirst && canReachSecond {
// 每次调用 DFS 前重置 visited 数组
for x := 0; x < N; x++ {
for y := 0; y < M; y++ {
visited[x][y] = false
}
}
canReachTopLeft, canReachBottomRight := dfs(grid, visited, i, j)
if canReachTopLeft && canReachBottomRight {
fmt.Println(strconv.Itoa(i) + " " + strconv.Itoa(j))
}
}
}
}


func dfs(grid [][]int, visited [][]bool, startx int, starty int) (bool, bool) {
// 标记当前单元格为已访问
visited[startx][starty] = true
canReachFirst := startx == 0 || starty == 0 || startx == len(grid)-1 || starty == len(grid[0])-1
canReachSecond := startx == len(grid)-1 || starty == len(grid[0])-1 || startx == 0 || starty == 0

if canReachFirst && canReachSecond {
// 判断是否能到达上边或左边的边界
canReachTopLeft := startx == 0 || starty == 0
// 判断是否能到达下边或右边的边界
canReachBottomRight := startx == len(grid)-1 || starty == len(grid[0])-1

// 如果已经同时到达两组边界,直接返回结果
if canReachTopLeft && canReachBottomRight {
return true, true
}



for _, direction := range directions {
nextx := startx + direction[0]
nexty := starty + direction[1]



if nextx < 0 || nextx >= len(grid) || nexty < 0 || nexty >= len(grid[0]) {
continue
}


// 如果下一个单元格的高度不大于当前单元格,且未被访问过,则递归调用 DFS
if grid[nextx][nexty] <= grid[startx][starty] && !visited[nextx][nexty] {
hasReachFirst, hasReachSecond := dfs(grid, visited, nextx, nexty)
if !canReachFirst {
canReachFirst = hasReachFirst
hasReachTopLeft, hasReachBottomRight := dfs(grid, visited, nextx, nexty)
// 更新是否能到达上边或左边边界的结果
if !canReachTopLeft {
canReachTopLeft = hasReachTopLeft
}
if !canReachSecond {
canReachSecond = hasReachSecond
// 更新是否能到达下边或右边边界的结果
if !canReachBottomRight {
canReachBottomRight = hasReachBottomRight
}
}
}
return canReachTopLeft, canReachBottomRight
}
```

优化解法

```go
package main

import (
"os"
"fmt"
"strings"
"strconv"
"bufio"
)

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

func main() {
scanner := bufio.NewScanner(os.Stdin)

scanner.Scan()
lineList := strings.Fields(scanner.Text())
N, _ := strconv.Atoi(lineList[0])
M, _ := strconv.Atoi(lineList[1])

grid := make([][]int, N)
for i := 0; i < N; i++ {
grid[i] = make([]int, M)
scanner.Scan()
lineList = strings.Fields(scanner.Text())
for j := 0; j < M; j++ {
grid[i][j], _ = strconv.Atoi(lineList[j])
}
}

// 初始化两个访问标记数组,分别记录从第一组边界和第二组边界可达的单元格
canReachTopLeft := make([][]bool, N)
canReachBottomRight := make([][]bool, N)
for i := 0; i < N; i++ {
canReachTopLeft[i] = make([]bool, M)
canReachBottomRight[i] = make([]bool, M)
}

// 从第一组边界(上边和左边)开始进行 DFS
for i := 0; i < N; i++ {
dfs(grid, canReachTopLeft, i, 0)
}
for j := 0; j < M; j++ {
dfs(grid, canReachTopLeft, 0, j)
}

// 从第二组边界(下边和右边)开始进行 DFS
for i := 0; i < N; i++ {
dfs(grid, canReachBottomRight, i, M-1)
}
for j := 0; j < M; j++ {
dfs(grid, canReachBottomRight, N-1, j)
}

// 找出同时能到达两组边界的单元格
for i := 0; i < N; i++ {
for j := 0; j < M; j++ {
if canReachTopLeft[i][j] && canReachBottomRight[i][j] {
fmt.Println(strconv.Itoa(i) + " " + strconv.Itoa(j))
}
}
}
return canReachFirst, canReachSecond
}

func dfs(grid [][]int, visited [][]bool, x, y int) {
visited[x][y] = true
for _, dir := range directions {
nextX := x + dir[0]
nextY := y + dir[1]
// 检查下一个单元格是否越界、是否已访问以及高度是否满足条件
if nextX >= 0 && nextX < len(grid) && nextY >= 0 && nextY < len(grid[0]) &&
!visited[nextX][nextY] && grid[nextX][nextY] >= grid[x][y] {
dfs(grid, visited, nextX, nextY)
}
}
}
```



### Rust

### JavaScript
Loading