欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Acwing 1402. 星空之夜 连通块哈希

程序员文章站 2022-07-12 22:54:08
...

Acwing 1402. 星空之夜

题意

给一个二维01矩阵,寻找连通块,相似的连通块用同一个字母表示,可以通过旋转、对称得到的就是相似。要求输出的矩阵字典序最小。

题解

  • dfs搜索即可
  • 哈希方式:计算每两个点的欧几里得距离之和,就是这个连通图的哈希值。相似的图形哈希值一定相同,大部分情况下是哈希值不会重复。

代码

#pragma region
//#pragma optimize("Ofast")
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <vector>
using namespace std;
typedef long long ll;
#define tr t[root]
#define lson t[root << 1]
#define rson t[root << 1 | 1]
#define rep(i, a, n) for (int i = a; i <= n; ++i)
#define per(i, a, n) for (int i = n; i >= a; --i)
#pragma endregion
const int maxn = 105;
int n, m;
char s[maxn][maxn];
int dir[8][2] = {{0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1}, {1, 0}, {1, 1}};
bool vis[maxn][maxn];
bool check(int x, int y) { return x >= 1 && x <= n && y >= 1 && y <= m && s[x][y] == '1' && !vis[x][y]; }
vector<pair<int, int>> v;
void dfs(int x, int y) {
    v.push_back({x, y}), vis[x][y] = 1;
    for (int i = 0; i < 8; ++i) {
        int nx = x + dir[i][0], ny = y + dir[i][1];
        if (check(nx, ny)) dfs(nx, ny);
    }
}
double getdis() {
    double ans = 0;
    for (int i = 0; i + 1 < v.size(); ++i) {
        for (int j = i + 1; j < v.size(); ++j) {
            double dx = v[i].first - v[j].first, dy = v[i].second - v[j].second;
            ans += sqrt(dx * dx + dy * dy);
        }
    }
    return ans;
}
map<ll, char> mp;
char now = 'a';
void solve() {
    double dis = getdis();
    ll tmp = ll(dis * 1e6);
    if (!mp[tmp]) mp[tmp] = now++;
    for (auto it : v) s[it.first][it.second] = mp[tmp];
}
int main() {
    scanf("%d%d", &m, &n);
    rep(i, 1, n) scanf("%s", s[i] + 1);
    rep(i, 1, n) rep(j, 1, m) {
        if (s[i][j] == '1') {
            v.clear();
            dfs(i, j);
            solve();
        }
    }
    rep(i, 1, n) puts(s[i] + 1);
}
相关标签: 瞎搞