在线评测链接:P1147
第一题太水了,群友已经忘记内容了。想必应该也是个人均都会的签到题。大家从第二题开始看吧
塔子哥是一个年轻的程序员,他热爱计算机科学和数学。他一直在思考如何利用计算机技术来解决实际问题。有一天,他接到了一项任务,要为一个遥远的星球上的一座城市设计一个城市规划系统。
这个城市非常大,由许多小区域组成。每个小区域都有一个 n ∗ m n * m n∗m 的矩阵,矩阵中的每个位置都取值为 W W W 或 R R R,分别代表白色和红色。这些小区域之间可能存在道路或其他障碍物,但每个小区域内部都是连通的。
塔子哥想知道,如果将任意位置 ( i , j ) (i,j) (i,j) 涂成白色后,会有多少个全红的连通块,求一个 n ∗ m n*m n∗m 的矩阵 a n s ans ans , a n s [ i ] [ j ] ans[i][j] ans[i][j] 表示将位置 ( i , j ) (i,j) (i,j) 涂成白色以后,剩下的全红连通块个数。 保证数据随机生成
第一行为两个整数 n n n 和 m m m ,( 1 ≤ n , m ≤ 40 1\le n,m \le 40 1≤n,m≤40 )
接下来 n n n 行,每行有 m m m 个字母,每个字母取值为 W W W 或 R R R 。
输出为一个 n ∗ m n*m n∗m 的矩阵。
输入
4 3
R W W
W R R
R R R
W W W
输出
1 2 2
2 2 2
2 3 2
2 2 2
非常经典的题。枚举所有点,把它改成白色,然后求一遍联通块个数。
复杂度: O ( n m ∗ n m ) = O ( n 2 m 2 ) O(nm * nm)=O(n^2m^2) O(nm∗nm)=O(n2m2)
1.学习割点:割点和桥 - Oi Wiki
2.原题来自:D.Router Mesh - 2020 ICPC小米选拔赛第一场
剑指 Offer II 105. 岛屿的最大面积
200. 岛屿数量
547. 朋友圈
P1094. 米哈游 2023.03.19-第一题-塔子哥的RBG矩阵
P1237 2023.04.15-美团实习-第三题-交通规划
#include
using namespace std;
const int maxn = 45, dirs[4][2]{-1, 0, 1, 0, 0, -1, 0, 1};
char colors[maxn][maxn];
bool vis[maxn][maxn];
int n, m;
void dfs(int x, int y) {
vis[x][y] = true;
for (auto &[dx, dy] : dirs) {
int nx = x + dx, ny = y + dy;
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny] && colors[nx][ny] == 'R') {
dfs(nx, ny);
}
}
}
// 求联通分量个数
int solve() {
memset(vis, 0, sizeof(vis));
int cnt = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (vis[i][j] || colors[i][j] == 'W') continue;
dfs(i, j);
cnt++;
}
}
return cnt;
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
cin >> colors[i][j];
}
}
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
char preColor = colors[i][j];
colors[i][j] = 'W';
int cnt = solve();
printf("%d ", cnt);
colors[i][j] = preColor;
}
printf("\n");
}
return 0;
}
// by yhy
dfs解法
n , m = list(map(int , input().split()))
a = []
for i in range(n):
a.append(list(map(str , input().split())))
dx = [0 , 0 , -1 , 1]
dy = [-1 , 1 , 0 , 0]
bk = set()
# dfs 求联通块个数
def dfs (x , y):
bk.add(f"{x} {y}")
for i in range (4):
nx = x + dx[i]
ny = y + dy[i]
if nx < 0 or nx >= n or ny < 0 or ny >= m or f"{nx} {ny}" in bk or a[nx][ny] == 'W':
continue
dfs(nx , ny)
def calc (x , y):
bk.clear()
t = a[x][y]
a[x][y] = 'W'
cnt = 0
for i in range (n):
for j in range (m):
if f"{i} {j}" in bk or a[i][j] == 'W':
continue
dfs(i , j)
cnt += 1
a[x][y] = t
return cnt
for i in range (n):
for j in range (m):
print (calc(i , j) , end = "")
if j == m - 1:
print()
else:
print(" " , end = "")
并查集解法
import java.util.*;
public class Main {
static int[][] dirs = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 上下左右四个方向
static int[] father; // 并查集数组
static int countRedBlocks; // 红色连通块个数
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int m = scanner.nextInt();
scanner.nextLine(); // 读取换行符
char[][] matrix = new char[n][m];
for (int i = 0; i < n; i++) {
matrix[i] = scanner.nextLine().replaceAll(" ", "").toCharArray();
}
int[][] ans = new int[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (matrix[i][j] == 'R') {
// 将颜色为 W 的格子修改为 R
matrix[i][j] = 'W';
// 统计剩余的红色连通块个数
ans[i][j] = countRedBlocks(matrix, n, m);
// 将颜色再改回来,以便下一次统计
matrix[i][j] = 'R';
} else {
ans[i][j] = countRedBlocks(matrix, n, m);
}
}
}
// 输出结果
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
System.out.print(ans[i][j] + " ");
}
System.out.println();
}
}
// 计算红色连通块个数
private static int countRedBlocks(char[][] matrix, int n, int m) {
// 初始化并查集
father = new int[n * m];
countRedBlocks = 0;
for (int i = 0; i < n * m; i++) {
father[i] = i;
if (matrix[i / m][i % m] == 'R') {
countRedBlocks++;
}
}
// 合并相邻格子中的红色连通块
for (int i = 0; i < n * m; i++) {
int x1 = i / m;
int y1 = i % m;
if (matrix[x1][y1] == 'R') {
for (int[] dir : dirs) {
int x2 = x1 + dir[0];
int y2 = y1 + dir[1];
if (x2 >= 0 && x2 < n && y2 >= 0 && y2 < m && matrix[x2][y2] == 'R') {
int p1 = find(i);
int p2 = find(x2 * m + y2);
if (p1 != p2) {
father[p1] = p2;
countRedBlocks--;
}
}
}
}
}
return countRedBlocks;
}
// 查找节点的根节点,并进行路径压缩优化
private static int find(int u) {
if (u != father[u]) {
father[u] = find(father[u]);
}
return father[u];
}
}
package main
import (
"bufio"
"fmt"
"os"
)
var dx = []int{0, 0, -1, 1}
var dy = []int{-1 , 1 , 0 , 0}
var bk = make(map[string]bool)
var a [][]string
var n, m int
// dfs求联通块
func dfs(x, y int) {
bk[fmt.Sprintf("%d %d", x, y)] = true
for i := 0; i < 4; i++ {
nx := x + dx[i]
ny := y + dy[i]
if nx < 0 || nx >= n || ny < 0 || ny >= m || bk[fmt.Sprintf("%d %d", nx, ny)] || a[nx][ny] == "W" {
continue
}
dfs(nx, ny)
}
}
// 将这个点涂白,求解连通分量个数
func calc(x, y int) int {
bk = make(map[string]bool)
t := a[x][y]
a[x][y] = "W"
cnt := 0
for i := 0; i < n; i++ {
for j := 0; j < m; j++ {
if bk[fmt.Sprintf("%d %d", i, j)] || a[i][j] == "W" {
continue
}
dfs(i, j)
cnt++
}
}
a[x][y] = t
return cnt
}
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Scanf("%d %d\n", &n, &m)
a = make([][]string, n)
for i := 0; i < n; i++ {
a[i] = make([]string, m)
line, _ := reader.ReadString('\n')
for j := 0; j < m; j++ {
fmt.Sscanf(string(line[j*2:j*2+1]), "%s", &a[i][j])
}
}
for i := 0; i < n; i++ {
for j := 0; j < m; j++ {
fmt.Printf("%d", calc(i, j))
if j == m-1 {
fmt.Println()
} else {
fmt.Print(" ")
}
}
}
}
let input = "";
process.stdin.resume();
process.stdin.setEncoding("utf-8");
process.stdin.on("data", (data) => {
input += data;
});
process.stdin.on("end", () => {
const lines = input.trim().split("\n");
const [n, m] = lines[0].trim().split(" ").map(Number);
const a = [];
for (let i = 1; i <= n; i++) {
const row = lines[i].trim().split(" ");
a.push(row);
}
// dfs 求联通块个数
const dx = [0, 0, -1, 1];
const dy = [-1, 1, 0, 0];
const bk = new Set();
function dfs(x, y) {
bk.add(`${x} ${y}`);
for (let i = 0; i < 4; i++) {
const nx = x + dx[i];
const ny = y + dy[i];
if (nx < 0 || nx >= n || ny < 0 || ny >= m || bk.has(`${nx} ${ny}`) || a[nx][ny] === "W") {
continue;
}
dfs(nx, ny);
}
}
// 将[x,y] 涂成白色 ,求连通分量个数
function calc(x, y) {
bk.clear();
const t = a[x][y];
a[x][y] = "W";
let cnt = 0;
for (let i = 0; i < n; i++) {
for (let j = 0; j < m; j++) {
if (bk.has(`${i} ${j}`) || a[i][j] === "W") {
continue;
}
dfs(i, j);
cnt++;
}
}
a[x][y] = t;
return cnt;
}
for (let i = 0; i < n; i++) {
let rowOutput = "";
for (let j = 0; j < m; j++) {
rowOutput += calc(i, j);
if (j === m - 1) {
rowOutput += "\n";
} else {
rowOutput += " ";
}
}
process.stdout.write(rowOutput);
}
});