#P3192. 相同数字组成图形的周长(200分)
-
1000ms
Tried: 150
Accepted: 32
Difficulty: 5
所属公司 :
华为od
-
算法标签>模拟
相同数字组成图形的周长(200分)
题面简述
我们有一个 64×64 的矩阵,所有元素默认值为 0,接着在矩阵中填充不同的数字。每个数字代表一个实心图形,图形由若干个相同数字的格子构成。题目要求我们计算每个数字图形的周长。具体来说,我们要计算每个数字所占区域的边界长度。如果相邻的格子是 0 或者超出矩阵边界,就计入周长。
解题思路
-
矩阵的表示与填充:
- 创建一个 64×64 的矩阵,初始化为 0。接着根据输入的数据,将相同数字填入相应的矩阵位置,形成不同的图形。
-
周长的计算:
- 每个格子都会检查它的四个方向(上下左右),如果某个方向的邻居数字不同或越界,则该边界会计入周长。
- 对于每个数字对应的填充位置,我们通过遍历这些坐标并计算它们的周长。
Python 实现
def calculate_perimeter(matrix, n, coords, num):
# 方向数组:分别是上、下、左、右
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
perimeter = 0
# 遍历每个填充数字的坐标,计算周长
for i in range(0, len(coords), 2):
x, y = coords[i], coords[i + 1]
# 对每个坐标点,检查四个方向的邻居
for dx, dy in directions:
nx, ny = x + dx, y + dy
# 如果邻居在矩阵外或是空白(值为0),则此边界贡献1
if nx < 0 or nx >= n or ny < 0 or ny >= n or matrix[nx][ny] != num:
perimeter += 1
return perimeter
def main():
# 读取输入
N = int(input()) # 输入图形的数量
matrix = [[0] * 64 for _ in range(64)] # 创建64x64的矩阵,初始化为0
input_data = []
# 读取所有图形的数据
for _ in range(N):
data = list(map(int, input().split()))
input_data.append(data)
# 填充矩阵
for data in input_data:
num = data[0] # 填充的数字
coords = data[1:] # 填充坐标
# 填充该数字到矩阵中
for i in range(0, len(coords), 2):
x, y = coords[i], coords[i + 1]
matrix[x][y] = num
results = []
# 计算每个图形的周长
for data in input_data:
num = data[0] # 填充的数字
coords = data[1:] # 填充坐标
# 计算该数字图形的周长
perimeter = calculate_perimeter(matrix, 64, coords, num)
results.append(str(perimeter))
# 输出所有图形的周长
print(" ".join(results))
if __name__ == "__main__":
main()
Java 实现
import java.util.*;
public class Main {
// 方向数组:分别是上、下、左、右
private static final int[][] DIRECTIONS = {
{-1, 0}, {1, 0}, {0, -1}, {0, 1}
};
// 计算周长的函数
private static int calculatePerimeter(int[][] matrix, int matrixSize, int[] coordinates, int num) {
int perimeter = 0;
// 遍历每个填充数字的坐标,计算周长
for (int i = 1; i < coordinates.length; i += 2) {
int x = coordinates[i];
int y = coordinates[i + 1];
// 对每个坐标点,检查四个方向的邻居
for (int[] direction : DIRECTIONS) {
int nx = x + direction[0];
int ny = y + direction[1];
// 如果邻居在矩阵外或是空白(值为0),则此边界贡献1
if (nx < 0 || nx >= matrixSize || ny < 0 || ny >= matrixSize || matrix[nx][ny] != num) {
perimeter++;
}
}
}
return perimeter;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取图形的数量
int shapeCount = Integer.parseInt(scanner.nextLine());
// 创建64x64的矩阵,初始化为0
int[][] matrix = new int[64][64];
// 用于存储输入的数据
List<int[]> shapesData = new ArrayList<>();
// 读取所有图形的数据
for (int i = 0; i < shapeCount; i++) {
String[] input = scanner.nextLine().split(" ");
int[] data = new int[input.length];
int num = Integer.parseInt(input[0]);
// 填充坐标
for (int j = 0; j < data.length; j++) {
data[j] = Integer.parseInt(input[j]);
}
shapesData.add(data);
// 填充该数字到矩阵中
for (int j = 1; j < data.length; j += 2) {
int x = data[j];
int y = data[j + 1];
matrix[x][y] = num;
}
}
List<String> results = new ArrayList<>();
// 计算每个图形的周长
for (int[] coordinates : shapesData) {
int num = coordinates[0]; // 填充的数字为 coordinates[0]
int perimeter = calculatePerimeter(matrix, 64, coordinates, num);
results.add(String.valueOf(perimeter));
}
// 输出所有图形的周长
System.out.println(String.join(" ", results));
scanner.close();
}
}
C++ 实现
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int calculatePerimeter(vector<vector<int>>& matrix, int n, vector<int>& coords,int num) {
// 方向数组:分别是上、下、左、右
vector<pair<int, int>> directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int sz = coords.size()/2;
int perimeter = sz*4;
// 遍历每个填充数字的坐标,计算周长
for (size_t i = 0; i < coords.size(); i += 2) {
int x = coords[i];
int y = coords[i + 1];
// 对每个坐标点,检查四个方向的邻居
for (auto& dir : directions) {
int nx = x + dir.first;
int ny = y + dir.second;
if (nx >= 0 && nx < n && ny >= 0 && ny < n && matrix[nx][ny] == num) {
perimeter -= 1;
}
}
}
return perimeter;
}
int main() {
int N;
cin >> N; // 输入图形的数量
vector<vector<int>> matrix(64, vector<int>(64, 0)); // 创建64x64的矩阵,初始化为0
cin.ignore(); // 忽略当前行的换行符
string line;
while(getline(cin,line)) {
if(line.empty()) continue;
stringstream ss(line);
vector<int> coords;
int x;
int num;
ss >> num;
while (ss >> x) {
coords.push_back(x);
}
// 填充该数字到矩阵中
for (size_t j = 0; j < coords.size(); j += 2) {
matrix[coords[j]][coords[j + 1]] = num;
}
// 计算每个图形的周长并输出
int perimeter = calculatePerimeter(matrix, 64, coords, num);
cout << perimeter << " ";
}
return 0;
}
题目内容
有一个64×64 的矩阵,每个元素的默认值为 0 ,现在向里面填充数字,相同的数字组成一个实心图形,如下图所示是矩阵的局部(空白表示填充 0 ):

数字 1 组成了蓝色边框的实心图形,数字 2 组成了红色边框的实心图形。
单元格的边长规定为 1 个单位。
请根据输入,计算每个非 0 值填充出来的实心圆形的周长。
输入描述
第一行输入 N ,表示 N 个图形, N>0 且 N<64×64
矩阵左上角单元格坐标记作 (0,0) ,第一个数字表示行号,第二个数字表示列号
接下来是 N 行,每行第一个数是矩阵单元格填充的数字, 后续每两个一组,表示填充该数字的单元格坐标
答题者无需考虑数据格式非法的场景,题目用例不考察数据格式
题目用例保证同一个填充值只会有一行输入数据
输出描述
一共输出 N 个数值,每个数值表示某一行输入表示图形的周长
输出顺序需和输入的隔行顺序保持一致,即第 1 个数是输入的第 1 个图形的周长,第 2 个数是输入的第 2 个图形的周长,以此类推
样例1
输入
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