ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【ACWing】1402. 星空之夜

2021-02-10 09:01:05  阅读:208  来源: 互联网

标签:le 星空 int double ++ 哈希 1402 size ACWing


题目地址:

https://www.acwing.com/problem/content/1404/

给定一个 m m m行 n n n列的二维 0 − 1 0-1 0−1矩阵 A A A,考虑所有的 1 1 1的八连通块,要求将所有的形状相同的八连通块标记为相同的小写字母,并且使得输出矩阵的时候,矩阵字典序最小。两个连通块形状相同是指,旋转 90 ° , 180 ° , 270 ° 90\degree, 180\degree, 270\degree 90°,180°,270°或者左右镜像翻转、上下镜像翻转之后能重合。

数据范围:
0 ≤ m , n ≤ 100 0\le m,n\le 100 0≤m,n≤100
0 ≤ s ≤ 500 0\le s\le 500 0≤s≤500
0 ≤ d ≤ 26 0\le d\le 26 0≤d≤26
1 ≤ t ≤ 160 1\le t\le 160 1≤t≤160
s s s为 1 1 1连通块数量, d d d为不同的连通块数量, t t t是每个 1 1 1连通块 1 1 1的数量

思路是哈希。对于一个八连通块 C C C,我们定义其哈希值为 ∑ ( x 1 , y 1 ) , ( x 2 , y 2 ) ∈ C , ( x 1 , y 1 ) ≠ ( x 2 , y 2 ) ∣ A [ x 1 ] [ y 1 ] − A [ x 2 ] [ y 2 ] ∣ 2 \sqrt{\sum_{(x_1,y_1),(x_2,y_2)\in C,(x_1,y_1)\ne (x_2,y_2)}|A[x_1][y_1]-A[x_2][y_2]|^2} (x1​,y1​),(x2​,y2​)∈C,(x1​,y1​)​=(x2​,y2​)∑​∣A[x1​][y1​]−A[x2​][y2​]∣2 ​我们可以一行一行,每行从左到右遍历,通过DFS搜集每个 1 1 1连通块的坐标,求得其哈希值,然后看一下这个哈希值是否出现过(这里哈希值是double类型的,不能直接用==,而要做差看是否小于一个很小数),如果出现过就标记为之前给它配的那个记号,否则给它以新的标记,按照顺序标记为 a b c d . . . abcd... abcd...。代码如下:

#include <iostream>
#include <cmath>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 110;
const double eps = 1e-6;

int n, m;
char g[N][N];
PII q[N * N];

double get_dist(PII a, PII b) {
    double dx = a.x - b.x, dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}

// 算一下当前q数组里存的1连通块的哈希值
double get_hash(int size) {
    double sum = 0;
    for (int i = 0; i < size; i++)
        for (int j = i + 1; j < size; j++)
            sum += get_dist(q[i], q[j]);
    return sum;
}

// 根据这个哈希值,返回其应该被标记为什么字母
char get_id(double key) {
    static double hash[30];
    static int id = 0;
    for (int i = 0; i < id; i++) 
    	// 如果该哈希值已存在,则返回之前给它配的那个字母
        if (fabs(hash[i] - key) < eps)
            return i + 'a';
    // 否则将该哈希值加入数组,并返回下一个还没使用的字母
    hash[id++] = key;
    return id - 1 + 'a';
}

void dfs(int x, int y, int& size) {
    q[size++] = {x, y};
    g[x][y] = '0';
    for (int a = x - 1; a <= x + 1; a++) 
        for (int b = y - 1; b <= y + 1; b++) {
            if (a == x && b == y) continue;
            if (0 <= a && a < m && 0 <= b && b < n && g[a][b] == '1')
                dfs(a, b, size);
        }
}

int main() {
    cin >> n >> m;
    for (int i = 0; i < m; i++) cin >> g[i];

    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            if (g[i][j] == '1') {
                int size = 0;
                dfs(i, j, size);
                char c = get_id(get_hash(size));
                for (int k = 0; k < size; k++) 
                    g[q[k].x][q[k].y] = c;
            }

    for (int i = 0; i < m; i++) cout << g[i] << endl;

    return 0;
}

时空复杂度 O ( m n ) O(mn) O(mn)。

标签:le,星空,int,double,++,哈希,1402,size,ACWing
来源: https://blog.csdn.net/qq_46105170/article/details/113778553

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有