AcWing1402. 星空之夜

  1. 题目

    夜空深处,闪亮的星星以星群的形式出现在人们眼中,形态万千。

    一个星群是指一组非空的在水平,垂直或对角线方向相邻的星星的集合。

    一个星群不能是一个更大星群的一部分。

    星群可能是相似的。

    如果两个星群的形状、包含星星的数目相同,那么无论它们的朝向如何,都认为它们是相似的。

    通常星群可能有 8 种朝向,如下图所示:

    在这里插入图片描述

    现在,我们用一个二维 01 矩阵来表示夜空,如果一个位置上的数字是 1,那么说明这个位置上有一个星星,否则这个位置上的数字应该是 0。

    给定一个夜空二维矩阵,请你将其中的所有星群用小写字母进行标记,标记时相似星群用同一字母,不相似星群用不同字母。

    标注星群就是指将星群中所有的 11 替换为小写字母。

  2. 输入格式

    第一行包含一个整数 W,表示矩阵宽度。

    第二行包含一个整数 H,表示矩阵高度。

    接下来 H 行,每行包含一个长度为 W 的 01 序列,用来描述整个夜空矩阵。

  3. 输出格式

    输出标记完所有星群后的二维矩阵。

    用小写字母标记星群的方法很多,我们将整个输出读取为一个字符串,能够使得这个字符串字典序最小的标记方式,就是我们想要的标记方式。

    输出这个标记方式标出的最终二维矩阵。

  4. 数据范围

    0≤W,H≤100
    0≤ 星群数量 ≤500,
    0≤ 不相似星群数量 ≤26,
    1≤ 星群中星星的数量 ≤160

  5. 输入样例

    23
    15
    10001000000000010000000
    01111100011111000101101
    01000000010001000111111
    00000000010101000101111
    00000111010001000000000
    00001001011111000000000
    10000001000000000000000
    00101000000111110010000
    00001000000100010011111
    00000001110101010100010
    00000100110100010000000
    00010001110111110000000
    00100001110000000100000
    00001000100001000100101
    00000001110001000111000
    
  6. 输出样例

    a000a0000000000b0000000
    0aaaaa000ccccc000d0dd0d
    0a0000000c000c000dddddd
    000000000c0b0c000d0dddd
    00000eee0c000c000000000
    0000e00e0ccccc000000000
    b000000e000000000000000
    00b0f000000ccccc00a0000
    0000f000000c000c00aaaaa
    0000000ddd0c0b0c0a000a0
    00000b00dd0c000c0000000
    000g000ddd0ccccc0000000
    00g0000ddd0000000e00000
    0000b000d0000f000e00e0b
    0000000ddd000f000eee000
    
  7. 样例解释
    样例对应的星空图如下:
    在这里插入图片描述
    答案对应的标记后星空图如下:
    在这里插入图片描述

  8. 代码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]));
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现 three.js 的昼夜切换,需要进行以下步骤: 1. 创建两个场景,一个表示白天,一个表示夜晚。 2. 创建两个光源,一个表示白天的太阳,一个表示夜晚的月亮或星星。 3. 创建两个天空盒,一个表示白天的天空,一个表示夜晚的星空。 4. 在切换时,将白天场景的光源和天空盒隐藏,夜晚场景的光源和天空盒显示。 5. 为了过渡平滑,可以使用 Tween.js 库来实现光源和天空盒的渐变效果。 示例代码: ``` // 创建白天场景 var dayScene = new THREE.Scene(); // 创建夜晚场景 var nightScene = new THREE.Scene(); // 创建白天光源 var sun = new THREE.DirectionalLight(0xffffff, 1); sun.position.set(0, 100, 0); dayScene.add(sun); // 创建夜晚光源 var moon = new THREE.PointLight(0xffffff, 0.5); moon.position.set(0, 100, 0); nightScene.add(moon); // 创建白天天空盒 var daySkybox = new THREE.Mesh( new THREE.BoxGeometry(10000, 10000, 10000), new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture('day_skybox.jpg'), side: THREE.BackSide }) ); dayScene.add(daySkybox); // 创建夜晚天空盒 var nightSkybox = new THREE.Mesh( new THREE.BoxGeometry(10000, 10000, 10000), new THREE.MeshBasicMaterial({ map: THREE.ImageUtils.loadTexture('night_skybox.jpg'), side: THREE.BackSide }) ); nightScene.add(nightSkybox); // 切换到夜晚 function switchToNight() { var tween = new TWEEN.Tween(sun) .to({ intensity: 0 }, 1000) .onComplete(function() { daySkybox.visible = false; nightSkybox.visible = true; moon.intensity = 0; var tween2 = new TWEEN.Tween(moon) .to({ intensity: 0.5 }, 1000) .start(); }) .start(); } // 切换到白天 function switchToDay() { var tween = new TWEEN.Tween(moon) .to({ intensity: 0 }, 1000) .onComplete(function() { nightSkybox.visible = false; daySkybox.visible = true; sun.intensity = 0; var tween2 = new TWEEN.Tween(sun) .to({ intensity: 1 }, 1000) .start(); }) .start(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值