为了更好的阅读体检,可以查看我的算法学习网
本题在线评测链接:P1355
有一个 64 64 64x 64 64 64的矩阵,每个元素的默认值为 0 0 0,现在向里面填充数字,相同的数字组成一个实心图形,如下图所示是矩阵的局部(空白表示填充 0 0 0)
0 0 0 | 1 1 1 | 2 2 2 | 3 3 3 | 4 4 4 | 5 5 5 | 6 6 6 | 7 7 7 | 8 8 8 | 9 9 9 | 10 10 10 | 11 11 11 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 0 0 | ||||||||||||
1 1 1 | 1 |
|||||||||||
2 2 2 | 1 |
1 |
1 |
|||||||||
3 3 3 | 1 |
1 |
1 |
2 |
2 |
|||||||
4 4 4 | 1 |
1 |
1 |
1 |
2 |
2 |
2 |
2 |
||||
5 5 5 | 1 |
1 |
2 |
2 |
2 |
2 |
2 |
|||||
6 6 6 | 2 |
2 |
2 |
2 |
2 |
|||||||
7 7 7 | 2 |
2 |
2 |
2 |
2 |
|||||||
8 8 8 | ||||||||||||
9 9 9 | ||||||||||||
10 10 10 | ||||||||||||
11 11 11 |
输入
2
1 1 3 2 2 2 3 2 4 3 2 3 3 3 4 4 1 4 2 4 3 4 4 5 2 5 3
2 3 7 3 8 4 5 4 6 4 7 4 8 5 4 5 5 5 6 5 7 5 8 6 4 6 5 6 6 6 7 6 8 7 4 7 5 7 6 7 7 7 8
输出
18 20
说明
无
对于矩阵中的每个同色连通块,其周长的计算为最外面的格子对应的最外面的边的长度之和。
于是问题转换为求出所有的同色连通块:
继续考虑,对于每个有颜色的格子,有 4 4 4条边,如果其四个方向上的格子的颜色都与其相同,则说明这个格子是一个内部的格子。
否则,这个格子必然是某一个同色连通块的边缘格子,考虑这个格子中对所处同色连通块有贡献的边的数量即可。
故至此,问题转换为求每个有颜色的格子,其上下左右四个相邻格子与其颜色不相等的颜色数量。
时间复杂度: O ( n 2 ) , n = 64 O(n^2), n = 64 O(n2),n=64
#include
using namespace std;
int n = 64;
const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, 1, 0, -1};
// 将一行数据拆分成若干个数,装进一个vector中
vector<int> split_to_vector(const string& s) {
vector<int> vec;
for (int i = 0; i < s.size(); ++i) {
if (!isdigit(s[i])) continue;
int t = 0;
int j = i;
while (j < s.size() && isdigit(s[j])) {
t = t * 10 + (s[j] - '0');
j += 1;
}
vec.emplace_back(t);
i = j - 1;
}
return vec;
}
int main()
{
int m;
cin >> m;
// 忽略输入 m 后留在缓冲区的换行符
cin.ignore();
// g 表示图形
vector<vector<int>> g(n, vector<int>(n));
// nums 表示所有出现在 g 中的值
vector<int> nums;
string s;
// C++ 读取一行方式
while(getline(cin, s)) {
if (s.empty()) continue;
vector<int> vec = split_to_vector(s);
nums.push_back(vec[0]);
for (int j = 1; j + 1 < vec.size(); j += 2) {
// 给对应的格子赋值
g[vec[j]][vec[j + 1]] = vec[0];
}
}
// 统计每个值的周长之和
map<int, int> val;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
// 当一个格子有值,才可能有边长
if (g[i][j] > 0) {
int v = g[i][j];
int res = 4;
for (int k = 0; k < 4; ++k) {
int nx = i + dx[k], ny = j + dy[k];
if (nx >= 0 && nx < n && ny >= 0 && ny < n && g[nx][ny] == v) {
res -= 1;
}
}
val[v] += res;
}
for (int i = 0; i < m; ++i) {
cout << val[nums[i]] << " \n"[i + 1 == m];
}
return 0;
}
n = 64
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]
# g 表示图形
g = [[0] * n for i in range(n)]
# nums 表示所有出现在 g 中的值
nums = []
m = int(input())
for i in range(m):
lst = list(map(int, input().split()))
nums.append(lst[0])
for j in range(1, len(lst), 2):
# 给对应的格子赋值
g[lst[j]][lst[j + 1]] = lst[0]
# 统计每个值的周长之和
val = {}
for i in range(n):
for j in range(n):
# 当一个格子有值,才可能有边长
if g[i][j] > 0:
v = g[i][j]
res = 4
for k in range(4):
nx, ny = i + dx[k], j + dy[k]
if 0 <= nx < n and 0 <= ny < n and g[nx][ny] == v:
res -= 1
val[v] = val.get(v, 0) + res
for i in range(m):
print(val[nums[i]], end="\n" if i + 1 == m else " ")
import java.util.*;
public class Main {
static int n = 64;
static int[] dx = {-1, 0, 1, 0};
static int[] dy = {0, 1, 0, -1};
// g 表示图形
static int[][] g = new int[n][n];
// nums 表示所有出现在 g 中的值
static List<Integer> nums = new ArrayList<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int m = Integer.parseInt(sc.nextLine());
for (int i = 0; i < m; i++) {
String[] line = sc.nextLine().split(" ");
int v = Integer.parseInt(line[0]);
nums.add(v);
for (int j = 1; j < line.length; j += 2) {
int x = Integer.parseInt(line[j]);
int y = Integer.parseInt(line[j + 1]);
// 给对应的格子赋值
g[x][y] = v;
}
}
// 统计每个值的周长之和
Map<Integer, Integer> val = new HashMap<>();
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
// 当一个格子有值,才会有边长
if (g[i][j] > 0) {
int v = g[i][j];
int res = 4;
for (int k = 0; k < 4; ++k) {
int nx = i + dx[k], ny = j + dy[k];
if (nx >= 0 && nx < n && ny >= 0 && ny < n && g[nx][ny] == v) {
res -= 1;
}
}
val.put(v, val.getOrDefault(v, 0) + res);
}
}
}
for (int i = 0; i < m; i++) {
System.out.print(val.get(nums.get(i)));
if (i + 1 == m) {
System.out.println();
} else {
System.out.print(" ");
}
}
}
}
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
const n = 64
var dx = [4]int{-1, 0, 1, 0}
var dy = [4]int{0, 1, 0, -1}
// g 表示图形
var g [n][n]int
// nums 表示所有出现在 g 中的值
var nums []int
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
m, _ := strconv.Atoi(scanner.Text())
nums = make([]int, m)
for i := 0; i < m; i++ {
scanner.Scan()
line := scanner.Text()
s := strings.Split(line, " ")
v, _ := strconv.Atoi(s[0])
nums[i] = v
for j := 1; j < len(s); j += 2 {
x, _ := strconv.Atoi(s[j])
y, _ := strconv.Atoi(s[j+1])
// 给对应的格子赋值
g[x][y] = v
}
}
// 统计每个值的周长之和
val := make(map[int]int)
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
// 当一个格子有值,才可能有边长
if g[i][j] > 0 {
v := g[i][j]
res := 4
for k := 0; k < 4; k++ {
nx := i + dx[k]
ny := j + dy[k]
if nx >= 0 && nx < n && ny >= 0 && ny < n && g[nx][ny] == v {
res -= 1
}
}
val[v] += res
}
}
}
for i := 0; i < m; i++ {
fmt.Print(val[nums[i]])
if i+1 == m {
fmt.Println()
} else {
fmt.Print(" ")
}
}
}
process.stdin.resume();
process.stdin.setEncoding('utf-8');
let input = '';
process.stdin.on('data', (data) => {
input += data;
return;
});
const n = 64;
const dx = [-1, 0, 1, 0];
const dy = [0, 1, 0, -1];
// g 表示图形
const g = new Array(n).fill(0).map(() => new Array(n).fill(0));
process.stdin.on('end', () => {
const lines = input.trim().split('\n');
let index = 0;
// nums 表示所有出现在 g 中的值
const nums = [];
const m = parseInt(lines[index++]);
for (let i = 0; i < m; i++) {
const s = lines[index++].trim().split(' ');
const v = parseInt(s[0]);
nums.push(v);
for (let j = 1; j < s.length; j += 2) {
const x = parseInt(s[j]);
const y = parseInt(s[j + 1]);
// 给对应的格子赋值
g[x][y] = v;
}
}
// 统计每个值的周长之和
const val = new Map();
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
// 当一个格子有值,才可能有边长
if (g[i][j] > 0) {
const v = g[i][j];
let res = 4;
for (let k = 0; k < 4; k++) {
let nx = i + dx[k], ny = j + dy[k]
if (nx >= 0 && nx < n && ny >= 0 && ny < n && g[nx][ny] === v) {
res -= 1;
}
}
val.set(v, (val.get(v) || 0) + res);
}
}
}
let res = '';
for (let i = 0; i < m; i++) {
res += val.get(nums[i]) + (i === m - 1 ? '\n' : ' ');
}
console.log(res);
});