-
题目
夜空深处,闪亮的星星以星群的形式出现在人们眼中,形态万千。
一个星群是指一组非空的在水平,垂直或对角线方向相邻的星星的集合。
一个星群不能是一个更大星群的一部分。
星群可能是相似的。
如果两个星群的形状、包含星星的数目相同,那么无论它们的朝向如何,都认为它们是相似的。
通常星群可能有 8 种朝向,如下图所示:
现在,我们用一个二维 01 矩阵来表示夜空,如果一个位置上的数字是 1,那么说明这个位置上有一个星星,否则这个位置上的数字应该是 0。
给定一个夜空二维矩阵,请你将其中的所有星群用小写字母进行标记,标记时相似星群用同一字母,不相似星群用不同字母。
标注星群就是指将星群中所有的 11 替换为小写字母。
-
输入格式
第一行包含一个整数 W,表示矩阵宽度。
第二行包含一个整数 H,表示矩阵高度。
接下来 H 行,每行包含一个长度为 W 的 01 序列,用来描述整个夜空矩阵。
-
输出格式
输出标记完所有星群后的二维矩阵。
用小写字母标记星群的方法很多,我们将整个输出读取为一个字符串,能够使得这个字符串字典序最小的标记方式,就是我们想要的标记方式。
输出这个标记方式标出的最终二维矩阵。
-
数据范围
0≤W,H≤100
0≤ 星群数量 ≤500,
0≤ 不相似星群数量 ≤26,
1≤ 星群中星星的数量 ≤160 -
输入样例
23 15 10001000000000010000000 01111100011111000101101 01000000010001000111111 00000000010101000101111 00000111010001000000000 00001001011111000000000 10000001000000000000000 00101000000111110010000 00001000000100010011111 00000001110101010100010 00000100110100010000000 00010001110111110000000 00100001110000000100000 00001000100001000100101 00000001110001000111000
-
输出样例
a000a0000000000b0000000 0aaaaa000ccccc000d0dd0d 0a0000000c000c000dddddd 000000000c0b0c000d0dddd 00000eee0c000c000000000 0000e00e0ccccc000000000 b000000e000000000000000 00b0f000000ccccc00a0000 0000f000000c000c00aaaaa 0000000ddd0c0b0c0a000a0 00000b00dd0c000c0000000 000g000ddd0ccccc0000000 00g0000ddd0000000e00000 0000b000d0000f000e00e0b 0000000ddd000f000eee000
-
样例解释
样例对应的星空图如下:
答案对应的标记后星空图如下:
-
代码1
import java.util.*; import java.io.*; public class Main { static List<Double> hash = new ArrayList<>(); static List<int[]> q = new ArrayList<>(); static int col; static int row; static char[][] g; public static void main(String[] args) { Scanner sc = new Scanner(System.in); // 指定星图的行和列 col = sc.nextInt(); row = sc.nextInt(); // 用g存储整个星图 g = new char[row][col]; for(int i = 0; i < row; i++) { String str = sc.next(); g[i] = str.toCharArray(); } for(int i = 0; i < row; i++) { for(int j = 0; j < col; j++) { // 如果当前坐标是星星 if(g[i][j] == '1') { q.clear(); dfs(i, j); // 获取星图的hash值 double val = get_hash(); // 不同hash值映射为字符 char c = get_char(val); for(int[] k: q) { int a = k[0]; int b = k[1]; g[a][b] = c; } } } } for(int i = 0; i < row; i++) { System.out.println(g[i]); } } // 遍历坐标[x, y], 将其相接触(8个方向)的星云存储在同一个列表中 public static void dfs(int x, int y) { q.add(new int[]{x, y}); g[x][y] = '0'; // 这里就是相邻的8个表格 for(int i = x - 1; i <= x + 1; i++) { for(int j = y - 1; j <= y + 1; j++) { if(i >= 0 && i < row && j >= 0 && j <col &&g[i][j] == '1') { dfs(i, j); } } } } // 计算星图的hash值 // 用星图中任意两个坐标之间的距离之和来表示该星图的hash值 // 虽然也存在不同图形有相同hash值的情况, 但是概率很低很低, 可以忽略 public static double get_hash() { double res = 0; for(int i = 0; i < q.size(); i++) { for(int j = 0; j < q.size(); j++) { res += get_dist(q.get(i), q.get(j)); } } return res; } // 不同hash值映射为字符 public static char get_char(double val) { for(int i = 0; i < hash.size(); i++) { // 如果当前hash值和列表中的元素值相差很小(1e-6) // 则直接返回该元素对应的字符 if(Math.abs(val - hash.get(i)) < 1e-6) { return (char)((i) + 'a'); } } // 如果没有, 则添加到列表中, 并返回对应的字符 hash.add(val); return (char)((hash.size() - 1) + 'a'); } // 计算两点间的距离 public static double get_dist(int[] a, int[] b) { return Math.sqrt((a[0] -b[0]) * (a[0] - b[0]) + (a[1] - b[1]) * (a[1] - b[1])); } }
AcWing1402. 星空之夜
最新推荐文章于 2024-08-10 07:14:43 发布