题意:给出一个八连通的星图,要求为其中相同的星星块形状标上相同的字符。旋转,对称之后如果相同算是相同。
思路:用Hash表存储不同的连通块,求出连通分量点的x和y的平均值。以每个点到平均值差的四次方作为哈希值。
#include <iostream>
using namespace std;
const int mod=1999997;
struct point
{
int x,y;
}p[165];
struct node
{
int flag,area,next;
__int64 det;
}edges[mod*3];
int head[mod],e;
int n,m,flag,num;
bool visit[105][105];
char source[105][105];
int dx[]={-1,-1,-1,0,1,1,1,0};
int dy[]={-1,0,1,1,1,0,-1,-1};
void add (int x,int y)
{
num++;
p[num].x=x;
p[num].y=y;
}
void DFS (int x,int y)
{
for (int i=0;i<8;i++)
{
int xx=x+dx[i];
int yy=y+dy[i];
if (xx>=1 && xx<=n && yy>=1 && yy<=m && visit[xx][yy]==false && source[xx][yy]=='1')
{
visit[xx][yy]=true;
add(xx,yy);
DFS(xx,yy);
}
}
}
int Hash (int area,__int64 det)
{
int key=det%mod;
for (int i=head[key];i!=-1;i=edges[i].next)
if (edges[i].area==area && edges[i].det==det)
return edges[i].flag;
edges[e].area=area;
edges[e].det=det;
edges[e].flag=flag++;
edges[e].next=head[key];
head[key]=e++;
return flag-1;
}
void Deal (int x,int y)
{
num=0;
add(x,y);
visit[x][y]=true;
DFS(x,y);
int sumx=0,sumy=0,i;
for (i=1;i<=num;i++)
{
sumx+=p[i].x;
sumy+=p[i].y;
}
double xx=1.0*sumx/num,yy=1.0*sumy/num;
double det=0;
for (i=1;i<=num;i++)
det+=1.0*(p[i].x-xx)*(p[i].x-xx)*(p[i].x-xx)*(p[i].x-xx)+1.0*(p[i].y-yy)*(p[i].y-yy)*(p[i].y-yy)*(p[i].y-yy);
int flag=Hash(num,(__int64)(det*10));
for (i=1;i<=num;i++)
source[p[i].x][p[i].y]=flag+'a';
}
int main ()
{
scanf("%d%d",&m,&n);
int i;
for (i=1;i<=n;i++)
scanf("%s",source[i]+1);
flag=0;
memset(visit,false,sizeof(visit));
memset(head,-1,sizeof(head));
e=0;
for (i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (visit[i][j]==false && source[i][j]=='1')
Deal(i,j);
for (i=1;i<=n;i++)
puts(source[i]+1);
return 0;
}