P2749 [USACO5.1]夜空繁星Starry Night
考察:Flood Fill + hash
思路:
首先连通点很容易找到,关键是判定星群是否相似.对计算机来说很难保存每个连通块形状再旋转比较.这里可以考虑hash映射.这里的经验值是计算连通块两两之间的距离,累加和,作为关键字.这里要用sqrt,不能直接用平方和.平方和更容易发生冲突,比如 : 圈起来的两个连通块都是距离平方和为20.
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <vector> 6 using namespace std; 7 const int N = 110; 8 const double eps = 1e-6; 9 typedef pair<int,int> PII; 10 char mp[N][N]; 11 int xx[8]={-1,1,0,0,-1,-1,1,1},yy[8]={0,0,-1,1,-1,1,-1,1}; 12 bool st[N][N]; 13 int m,n,idx; 14 double h[30]; 15 vector<PII> v; 16 void dfs(int x,int y) 17 { 18 v.push_back({x,y}); 19 st[x][y] = 1; 20 for(int i=0;i<8;i++) 21 { 22 int dx = x+xx[i],dy = y+yy[i]; 23 if(dx>0&&dx<=n&&dy>0&&dy<=m&&mp[dx][dy]=='1'&&!st[dx][dy]) 24 { 25 st[dx][dy] = 1; 26 dfs(dx,dy); 27 } 28 } 29 } 30 double get() 31 { 32 double sum =0; 33 for(int i=0;i<v.size();i++) 34 for(int j=0;j<i;j++) 35 { 36 int x = v[i].first,y = v[i].second; 37 int a = v[j].first,b = v[j].second; 38 sum += sqrt((x-a)*(x-a)+(y-b)*(y-b)); 39 } 40 return sum; 41 } 42 int hashs(double d) 43 { 44 for(int i=0;i<idx;i++) 45 if(fabs(h[i]-d)<eps) return i; 46 return idx; 47 } 48 void getcolor(int idx) 49 { 50 char c = idx+'a'; 51 for(int i=0;i<v.size();i++) 52 { 53 int x = v[i].first,y = v[i].second; 54 mp[x][y] = c; 55 } 56 } 57 int main() 58 { 59 scanf("%d%d",&m,&n); 60 for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); 61 for(int i=1;i<=n;i++) 62 for(int j=1;j<=m;j++) 63 if(!st[i][j]&&mp[i][j]=='1') 64 { 65 v.clear(); 66 dfs(i,j); 67 double dist = get(); 68 int id = hashs(dist); 69 h[id] = dist; 70 getcolor(id); 71 if(id==idx) idx++; 72 } 73 for(int i=1;i<=n;i++) printf("%s\n",mp[i]+1); 74 return 0; 75 }