スターナイト(dfs)

夜空の奥深くに、輝く星が星団の形でさまざまな形で人々の目に現れます。

星座とは、水平方向、垂直方向、または対角線方向に隣接する空でない星のグループを指します。

コンステレーションをより大きなコンステレーションの一部にすることはできません。

星座は似ているかもしれません。

2つの星座の形と星の数が同じである場合、それらは向きに関係なく類似していると見なされます。

次の図に示すように、一般に、星座には8つの方向があります。

ここに画像の説明を挿入
ここで、2次元の01行列を使用して夜空を表します。ある位置の数が1の場合、この位置に星があります。それ以外の場合、この位置の数は0になります。

夜空の2次元マトリックスを前提として、その中のすべての星座を小文字でマークしてください。類似した星座をマークする場合は同じ文字を使用し、異なる星座は異なる文字を使用します。

コンステレーションにラベルを付けるとは、コンステレーション内のすべての1を小文字に置き換えることを意味します。

入力フォーマット

最初の行には、行列の幅を表す整数Wが含まれています。

2行目には、行列の高さを表す整数Hが含まれています。

次のH行では、各行に長さWの01シーケンスが含まれています。これは、夜空マトリックス全体を記述するために使用されます。

出力フォーマット

すべてのコンスタレーションをマークした後、2次元行列を出力します。

星座を小文字でマークする方法はたくさんあります。出力全体を文字列として読み取ります。文字列を辞書式に最小化できるマーク方法は、必要なマーク方法です。

このマーキング方法でマーキングされた最終的な2次元行列を出力します。

データ範囲

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

dfsとハッシュのアイデアが使用されます

星座のポイントだけでなく、星座の形も記録する必要があります

ポイントの場合、変数cntを使用して記録できます

形状については、星座内の任意の2点の距離の合計を計算し、それらを累積するトリックがあります。距離の合計は一意です。つまり、次のようになります。

∑x∈D、y∈D(x≠y)∣ ∣ x --y ∣ ∣ ∑_ {x∈D、y∈D〜(x≠y)} || xy || X D Y D X = y Σ| | Xy

計算されたすべての距離を配列に入れ、配列をトラバースするたびに、値が等しいかどうかを判断し、現在の距離の合計が表示されているかどうかを確認します

また、ダブルタイプですので、判断が等しい場合はepsを追加する必要があります

#include <bits/stdc++.h>
using namespace std;
const int N = 105;
#define x first
#define y second

int n, m, cnt; // cnt表示当前连通块的点数
char g[N][N], mark;
bool vis[N][N];
typedef pair<int, int> PII;
PII shape[N * N]; // 记录每个连通块的所有位置
// 计算两点间的距离
double get_dist(PII a, PII b)
{
    
    
    double x = a.x - b.x;
    double y = a.y - b.y;
    return sqrt(x * x + y * y);
}
// 得到距离之和
double get_hash()
{
    
    
    double res = 0;
    for (int i = 0; i < cnt; i++) {
    
    
        for (int j = i + 1; j < cnt; j++) {
    
    
            res += get_dist(shape[i], shape[j]);
        }
    }
    return res;
}
// 得到连通块的标记
char get_id(double v)
{
    
    
    static double hash[N]; // 记录所有连通块的距离
    static int cnt = 0;
    for (int i = 0; i < cnt; i++) {
    
    
        if (fabs(v - hash[i]) < 1e-6) {
    
    
            return 'a' + i;
        }
    }
    hash[cnt++] = v;
    return 'a' + cnt - 1;
}

void dfs(int x, int y)
{
    
    
    // 记录位置
    shape[cnt++] = {
    
    x, y};
    //cout << cnt << endl;
    vis[x][y] = 1;
    for (int dx = -1; dx <= 1; dx++) {
    
    
        for (int dy = -1; dy <= 1; dy++) {
    
    
            int nx = x + dx, ny = y + dy;
            if (nx >= 0 && nx < n && ny >= 0 && ny < m && g[nx][ny] == '1' && vis[nx][ny] == 0) {
    
    
                dfs(nx, ny);
            }
        }
    }
}

int main(void)
{
    
    
    cin >> m >> n;
    for (int i = 0; i < n; i++) {
    
    
        cin >> g[i];
    }
    for (int i = 0; i < n; i++) {
    
    
        for (int j = 0; j < m; j++) {
    
    
            cin >> g[i][j];
            if (g[i][j] == '1') {
    
    
                // 初始化连通块的点数
                cnt = 0;
                dfs(i, j);
                // 得到哈希(距离之和)
                double hash = get_hash();
                // 得到对应的标记
                mark = get_id(hash);
                // 标记连通块
                for (int k = 0; k < cnt; k++) {
    
    
                    g[shape[k].x][shape[k].y] = mark;
                }
            }
        }
    }
    for (int i = 0; i < n; i++) {
    
    
        for (int j = 0; j < m; j++) {
    
    
            cout << g[i][j];
        }
        cout << endl;
    }
    
    return 0;
}

おすすめ

転載: blog.csdn.net/weixin_43772166/article/details/113279217