zoukankan      html  css  js  c++  java
  • 夜空繁星(BFS,哈希)

    题意

    数据范围

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

    思路

    这个的关键主要是找到判定两个星群相似的方法。
    下面有一个定理:若一个星群中所有点两两距离的和,与另一个星群相等,那么这两个星群相似。
    这里给出一个直观的证明:将星群视为一个多边形,这些距离将多边形划分为一个个三角形,两个多边形划分的所有三角形全等,那个两个多边形相似。
    下面证明两个多边形对应三角形全等:因为距离和相等,并且一格的长度是1,因此对应三角形的对应边都是相等的。

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <queue>
    
    using namespace std;
    
    typedef pair<int, int> pii;
    
    const int N = 110, M = N * N;
    const double eps = 1e-6;
    
    int n, m;
    char g[N][N];
    pii point[M];
    int cnt;
    bool st[N][N];
    double hash_val[M];
    int num;
    
    int dx[8] = {-1, -1, -1, 0, 0, 1, 1, 1};
    int dy[8] = {-1, 0, 1, -1, 1, -1, 0, 1};
    
    double get_dist(pii a, pii b)
    {
        double dx = a.first - b.first;
        double dy = a.second - b.second;
        return sqrt(dx * dx + dy * dy);
    }
    
    double get_hash()
    {
        double res = 0;
        for(int i = 0; i < cnt; i ++) {
            for(int j = i + 1; j < cnt; j ++) {
                res += get_dist(point[i], point[j]);
            }
        }
        return res;
    }
    
    char get_id(double hash)
    {
        for(int i = 0; i < num; i ++) {
            if(fabs(hash_val[i] - hash) < eps) {
                return i + 'a';
            }
        }
        hash_val[num] = hash;
        num ++;
        return num - 1 + 'a';
    }
    
    void bfs(int ax, int ay)
    {
        cnt = 0;
        queue<pii> que;
        que.push({ax, ay});
        st[ax][ay] = true;
        point[cnt] = {ax, ay};
        cnt ++;
        while(que.size()) {
            auto t = que.front();
            que.pop();
            int tx = t.first, ty = t.second;
            for(int i = 0; i < 8; i ++) {
                int x = tx + dx[i], y = ty + dy[i];
                if(st[x][y]) continue;
                if(x < 1 || x > n || y < 1 || y > m) continue;
                if(g[x][y] != '1') continue;
                que.push({x, y});
                st[x][y] = true;
                point[cnt] = {x, y};
                cnt ++;
            }
        }
    }
    
    int main()
    {
        scanf("%d%d", &m, &n);
        for(int i = 1; i <= n; i ++) scanf("%s", g[i] + 1);
        for(int i = 1; i <= n; i ++) {
            for(int j = 1; j <= m; j ++) {
                if(g[i][j] == '1') {
                    bfs(i, j);
                    double hash = get_hash();
                    char ch = get_id(hash);
                    for(int k = 0; k < cnt; k ++) {
                        int x = point[k].first, y = point[k].second;
                        g[x][y] = ch;
                    }
                }
            }
        }
        for(int i = 1; i <= n; i ++) printf("%s
    ", g[i] + 1);
        return 0;
    }
    
  • 相关阅读:
    C#:BackgroundWorker的简单使用
    C#:DataTable 操作
    树和二叉树
    Git下的标签
    python的高级应用
    字符串匹配的BF算法和KMP算法学习
    GitHub:多人协作下的分支处理
    Git:分支的创建、合并、管理和删除
    GitHub:创建和修改远程仓库
    Git:文件操作和历史回退
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14341836.html
Copyright © 2011-2022 走看看