#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