1402.星空之夜(哈希映射)

题目链接:https://www.acwing.com/problem/content/description/1404/
这题非常有意思,让我学到了连通块的哈希映射方式,看题目时发现这题最大的难点是如何辨识“星群”,八个不同的方向需要如何映射成一个确定的字母值,想了许久没有任何可行思路。忍不住看了下题解才知道是映射各个连通点之间的距离之和。
题解思路如下:
1:首先存取下深搜过程的连通块坐标点。
2:计算连通块各点之间的距离和,计算欧几里得距离(我一开始用的没有开根的欧几里得距离的整数值映射,过不了最后的数据点,说明冲突较大,利用double小数的特性,能减少哈希冲突概率/曼哈顿距离也不行)进行哈希映射。
题外话,从这个映射方式让我开始思考,是否现在的图片识别就是用类似这种原理的算法,将图片像素点抽象成矩阵。再借此哈希映射来查看相似度。
代码如下

#include<bits/stdc++.h>
#define endl '\n';
using namespace std;
const int mod=1e9+7;
typedef long long  ll;
const int N=1e4;
int n,m;
char maps[500][500];
int stepx[9]={0,-1,-1,0,1,1,1,0,-1};
int stepy[9]={0,0,-1,-1,-1,0,1,1,1};
vector<double>hashs;
void dfs(int x,int y,vector<pair<int,int>>&q)
{
   
    q.push_back({x,y});
    maps[x][y]='0';
    for(int i=1;i<=8;i++)
    {
        int dx=stepx[i]+x;
        int dy=stepy[i]+y;
        if(dx<=0||dy<=0||dx>n||dy>m||maps[dx][dy]=='0')continue;
        dfs(dx,dy,q);
    }
}
double get_distance(vector<pair<int,int>>&q)//计算连通距离和
{
    double sum=0;
    for(int i=0;i<q.size();i++)
    {
        int x=q[i].first;
        int y=q[i].second;
        for(int j=i+1;j<q.size();j++)
        {
            int x2=q[j].first;
            int y2=q[j].second;
            sum+=sqrt((x-x2)*(x-x2)+(y-y2)*(y-y2));
        }
    }
    return sum;

}
void turn(vector<pair<int,int>>&q,char c)//将连通块转变成字母
{
    for(int i=0;i<q.size();i++)
    {
        int x=q[i].first;
        int y=q[i].second;
        maps[x][y]=c;
    }
    
    return;;
}
char check(double x)
{
    for(int i=0;i<hashs.size();i++)
    {
        if(fabs(hashs[i]-x)<1e-6)return i+'a';//查找哈希表
    }
    char c=hashs.size()+'a';
    hashs.push_back(x);
    return c;
    
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>m>>n;
    
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>maps[i][j];
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(maps[i][j]=='1')
            {
                
                vector<pair<int,int>>q;
                dfs(i,j,q);
                double sum=get_distance(q);
                char c=check(sum);
                turn(q,c);
                
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)cout<<maps[i][j];
        cout<<endl;
    }
    
  
    return 0;
}
posted @ 2023-06-06 22:04  五柳呢  阅读(12)  评论(0)    收藏  举报