diff --git "a/problems/kamacoder/0053.\345\257\273\345\256\235-Kruskal.md" "b/problems/kamacoder/0053.\345\257\273\345\256\235-Kruskal.md" index 861efe6806..1457cad798 100644 --- "a/problems/kamacoder/0053.\345\257\273\345\256\235-Kruskal.md" +++ "b/problems/kamacoder/0053.\345\257\273\345\256\235-Kruskal.md" @@ -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 diff --git "a/problems/kamacoder/0053.\345\257\273\345\256\235-prim.md" "b/problems/kamacoder/0053.\345\257\273\345\256\235-prim.md" index 8e26bea4bd..f482d5c38d 100644 --- "a/problems/kamacoder/0053.\345\257\273\345\256\235-prim.md" +++ "b/problems/kamacoder/0053.\345\257\273\345\256\235-prim.md" @@ -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 diff --git "a/problems/kamacoder/0103.\346\260\264\346\265\201\351\227\256\351\242\230.md" "b/problems/kamacoder/0103.\346\260\264\346\265\201\351\227\256\351\242\230.md" index 3066c99f28..290a21d1ea 100644 --- "a/problems/kamacoder/0103.\346\260\264\346\265\201\351\227\256\351\242\230.md" +++ "b/problems/kamacoder/0103.\346\260\264\346\265\201\351\227\256\351\242\230.md" @@ -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 diff --git "a/problems/kamacoder/0104.\345\273\272\351\200\240\346\234\200\345\244\247\345\262\233\345\261\277.md" "b/problems/kamacoder/0104.\345\273\272\351\200\240\346\234\200\345\244\247\345\262\233\345\261\277.md" index ffb6cae34d..66d9743210 100644 --- "a/problems/kamacoder/0104.\345\273\272\351\200\240\346\234\200\345\244\247\345\262\233\345\261\277.md" +++ "b/problems/kamacoder/0104.\345\273\272\351\200\240\346\234\200\345\244\247\345\262\233\345\261\277.md" @@ -528,6 +528,96 @@ if __name__ == "__main__": ### Go +```go +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +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]) + } + } + + mark := 2 // 从2开始标记岛屿,1表示原始陆地,0表示水 + islandArea := make(map[int]int) + for i := 0; i < N; i++ { + for j := 0; j < M; j++ { + if grid[i][j] == 1 { + area := dfs(grid, i, j, N, M, mark) + islandArea[mark] = area + mark++ + } + } + } + + maxArea := 0 + for _, area := range islandArea { + if area > maxArea { + maxArea = area + } + } + + for i := 0; i < N; i++ { + for j := 0; j < M; j++ { + if grid[i][j] == 0 { + adjacentIslands := make(map[int]bool) + for _, dir := range directions { + nx, ny := i+dir[0], j+dir[1] + if nx >= 0 && nx < N && ny >= 0 && ny < M && grid[nx][ny] > 1 { + adjacentIslands[grid[nx][ny]] = true + } + } + newArea := 1 // 当前水格变为陆地 + for island := range adjacentIslands { + newArea += islandArea[island] + } + if newArea > maxArea { + maxArea = newArea + } + } + } + } + + fmt.Println(maxArea) +} + +func dfs(grid [][]int, x, y, N, M, mark int) int { + if x < 0 || x >= N || y < 0 || y >= M || grid[x][y] != 1 { + return 0 + } + grid[x][y] = mark // 标记当前岛屿 + area := 1 + for _, dir := range directions { + nx, ny := x+dir[0], y+dir[1] + area += dfs(grid, nx, ny, N, M, mark) + } + return area +} +``` + + + ### Rust ### JavaScript diff --git "a/problems/kamacoder/0108.\345\206\227\344\275\231\350\277\236\346\216\245.md" "b/problems/kamacoder/0108.\345\206\227\344\275\231\350\277\236\346\216\245.md" index 121c2bfd43..e1a40449bf 100644 --- "a/problems/kamacoder/0108.\345\206\227\344\275\231\350\277\236\346\216\245.md" +++ "b/problems/kamacoder/0108.\345\206\227\344\275\231\350\277\236\346\216\245.md" @@ -219,6 +219,66 @@ if __name__ == "__main__": ### Go +```go +package main + +import ( + "fmt" + "os" + "bufio" +) + +var n int + +var father [1001]int + +func initUnionFind() { + for i := 1; i <= n; i++ { + father[i] = i + } +} + +func find(u int) int { + if father[u] == u { + return u + } + father[u] = find(father[u]) + return father[u] +} + +func isSame(u, v int) bool { + return find(u) == find(v) +} + +func join(u, v int) { + rootU := find(u) + rootV := find(v) + if rootV != rootU { + father[rootU] = rootV + } +} + +func main() { + var s, t int + scanner := bufio.NewScanner(os.Stdin) + scanner.Scan() + fmt.Sscanf(scanner.Text(), "%d", &n) + initUnionFind() + for i := 0; i < n; i++ { + scanner.Scan() + fmt.Sscanf(scanner.Text(), "%d %d", &s, &t) + if isSame(find(s), find(t)) {//判断是否在同一个集合,如果在,就说明存在环,打印即可 + fmt.Println(s, t) + break + } else { + join(s, t) //如果不存在,就加入集合, + } + } +} +``` + + + ### Rust ### JavaScript diff --git "a/problems/kamacoder/0109.\345\206\227\344\275\231\350\277\236\346\216\245II.md" "b/problems/kamacoder/0109.\345\206\227\344\275\231\350\277\236\346\216\245II.md" index 070bc68500..74c6f5ed59 100644 --- "a/problems/kamacoder/0109.\345\206\227\344\275\231\350\277\236\346\216\245II.md" +++ "b/problems/kamacoder/0109.\345\206\227\344\275\231\350\277\236\346\216\245II.md" @@ -465,6 +465,120 @@ if __name__ == "__main__": ### Go +```go +package main + +import ( + "fmt" + "os" + "bufio" +) + +var n int +var father [1001]int +var edges [][]int + +// 并查集初始化 +func initUnionFind() { + for i := 1; i <= n; i++ { + father[i] = i + } +} + +// 并查集里寻根的过程 +func find(u int) int { + if u == father[u] { + return u + } + father[u] = find(father[u]) + return father[u] +} + +// 将v->u这条边加入并查集 +func join(u, v int) { + u = find(u) + v = find(v) + if u != v { + father[v] = u + } +} + +// 判断u和v是否找到同一个根 +func isSame(u, v int) bool { + return find(u) == find(v) +} + +// 在有向图里找到删除的那条边,使其变成树 +func getRemoveEdge() {//冗余连接 + initUnionFind() // 初始化并查集 + for i := 0; i < n; i++ { // 遍历所有的边 + if isSame(edges[i][0], edges[i][1]) { // 构成有向环了,就是要删除的边 + fmt.Println(edges[i][0], edges[i][1]) + return + } else { + join(edges[i][0], edges[i][1]) + } + } +} + +// 删一条边之后判断是不是树 +func isTreeAfterRemoveEdge(deleteEdge int) bool { + initUnionFind() // 初始化并查集 + for i := 0; i < n; i++ { + if i == deleteEdge { + continue + } + if isSame(edges[i][0], edges[i][1]) { // 构成有向环了,一定不是树 + return false + } + join(edges[i][0], edges[i][1]) + } + return true +} + +func main() { + scanner := bufio.NewScanner(os.Stdin) + scanner.Scan() + fmt.Sscanf(scanner.Text(), "%d", &n) + + inDegree := make([]int, n+1) // 记录节点入度 + edges = make([][]int, n) + + for i := 0; i < n; i++ { + var s, t int + scanner.Scan() + fmt.Sscanf(scanner.Text(), "%d %d", &s, &t) + inDegree[t]++ + edges[i] = []int{s, t} + } + + vec := []int{} // 记录入度为2的边(如果有的话就两条边) + // 找入度为2的节点所对应的边,注意要倒序,因为优先删除最后出现的一条边 + for i := n - 1; i >= 0; i-- { + if inDegree[edges[i][1]] == 2 { + vec = append(vec, i) + } + } + + // 情况一、情况二 + if len(vec) > 0 { + // 放在vec里的边已经按照倒序放的,所以这里就优先删vec[0]这条边 + if isTreeAfterRemoveEdge(vec[0]) { + fmt.Println(edges[vec[0]][0], edges[vec[0]][1]) + } else { + fmt.Println(edges[vec[1]][0], edges[vec[1]][1]) + } + return + } + + // 处理情况三 + // 明确没有入度为2的情况,那么一定有有向环,找到构成环的边返回就可以了 + getRemoveEdge() +} +``` + + + ### Rust ### JavaScript diff --git "a/problems/\350\203\214\345\214\205\351\227\256\351\242\230\347\220\206\350\256\272\345\237\272\347\241\200\345\244\232\351\207\215\350\203\214\345\214\205.md" "b/problems/\350\203\214\345\214\205\351\227\256\351\242\230\347\220\206\350\256\272\345\237\272\347\241\200\345\244\232\351\207\215\350\203\214\345\214\205.md" index 878efc1297..d7cc68c399 100644 --- "a/problems/\350\203\214\345\214\205\351\227\256\351\242\230\347\220\206\350\256\272\345\237\272\347\241\200\345\244\232\351\207\215\350\203\214\345\214\205.md" +++ "b/problems/\350\203\214\345\214\205\351\227\256\351\242\230\347\220\206\350\256\272\345\237\272\347\241\200\345\244\232\351\207\215\350\203\214\345\214\205.md" @@ -229,6 +229,86 @@ print(dp[-1]) ### Go: +```go +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +func main() { + // 读取输入 + reader := bufio.NewReader(os.Stdin) + + line, _ := reader.ReadString('\n') + line = strings.TrimSpace(line) + cn := strings.Fields(line) + C, _ := strconv.Atoi(cn[0]) + N, _ := strconv.Atoi(cn[1]) + + // 读取重量 + line, _ = reader.ReadString('\n') + line = strings.TrimSpace(line) + weightStr := strings.Fields(line) + weight := make([]int, N) + for i := 0; i < N; i++ { + weight[i], _ = strconv.Atoi(weightStr[i]) + } + + // 读取价格 + line, _ = reader.ReadString('\n') + line = strings.TrimSpace(line) + priceStr := strings.Fields(line) + price := make([]int, N) + for i := 0; i < N; i++ { + price[i], _ = strconv.Atoi(priceStr[i]) + } + + // 读取数量 + line, _ = reader.ReadString('\n') + line = strings.TrimSpace(line) + numsStr := strings.Fields(line) + nums := make([]int, N) + for i := 0; i < N; i++ { + nums[i], _ = strconv.Atoi(numsStr[i]) + } + + // 转化成01背包 + extendedWeight := []int{} + extendedPrice := []int{} + for i := 0; i < N; i++ { + for j := 0; j < nums[i]; j++ { + extendedWeight = append(extendedWeight, weight[i]) + extendedPrice = append(extendedPrice, price[i]) + } + } + + // 动态规划 + dp := make([]int, C+1) + + for i := 0; i < len(extendedWeight); i++ { + for j := C; j >= extendedWeight[i]; j-- { + dp[j] = maxInt(dp[j], dp[j-extendedWeight[i]]+extendedPrice[i]) + } + } + + fmt.Println(dp[C]) +} + +func maxInt(a, b int) int { + if a > b { + return a + } + return b +} +``` + + + ### TypeScript: @@ -241,3 +321,4 @@ print(dp[-1]) + diff --git "a/problems/\350\203\214\345\214\205\351\227\256\351\242\230\347\220\206\350\256\272\345\237\272\347\241\200\345\256\214\345\205\250\350\203\214\345\214\205.md" "b/problems/\350\203\214\345\214\205\351\227\256\351\242\230\347\220\206\350\256\272\345\237\272\347\241\200\345\256\214\345\205\250\350\203\214\345\214\205.md" index ea658f7e51..d97c9be3a6 100644 --- "a/problems/\350\203\214\345\214\205\351\227\256\351\242\230\347\220\206\350\256\272\345\237\272\347\241\200\345\256\214\345\205\250\350\203\214\345\214\205.md" +++ "b/problems/\350\203\214\345\214\205\351\227\256\351\242\230\347\220\206\350\256\272\345\237\272\347\241\200\345\256\214\345\205\250\350\203\214\345\214\205.md" @@ -280,6 +280,64 @@ public class Main { ### Go +```go +package main + +import ( + "bufio" + "fmt" + "os" + "strconv" + "strings" +) + +func main() { + // 读取输入 + reader := bufio.NewReader(os.Stdin) + + // 读取 n 和 v + line, _ := reader.ReadString('\n') + line = strings.TrimSpace(line) + nv := strings.Fields(line) + n, _ := strconv.Atoi(nv[0]) + v, _ := strconv.Atoi(nv[1]) + + kinds := make([]int, n) + weight := make([]int, n) + + for i := 0; i < n; i++ { + line, _ := reader.ReadString('\n') + line = strings.TrimSpace(line) + parts := strings.Fields(line) + kinds[i], _ = strconv.Atoi(parts[0]) + weight[i], _ = strconv.Atoi(parts[1]) + } + + dp := make([]int, v+1) + + for i := 0; i < n; i++ { + for j := 0; j <= v; j++ { + if j-kinds[i] >= 0 { + dp[j] = maxInt(dp[j], dp[j-kinds[i]]+weight[i]) + } + } + } + + + + fmt.Println(dp[v]) +} + +func maxInt(a, b int) int { + if a > b { + return a + } + return b +} +``` + + + ### Python ```python @@ -366,3 +424,4 @@ readline.on('close', () => { +