数据不大,但细节要注意。这道题的基本方法就是Floodfill,找到所有的连通块,把全等的连通块标识起来。
寻找全等连通块的方法很多,我的方法是把每个连通块散列存储起来。找到一个新的连通块的时候把它和旋转对称变换所得8个图形分别进行散列,然后在哈希表中查找是否出现过。如果出现过,新的连通块与以前的全等。如果没有出现,则找到了一个新的连通块,标识并存储即可。
/*
PROB: starry
LANG: C++
ID: xsy97051
*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 1<<20
typedef char Ima[100][101];
int h,w;
Ima start,final;
struct node{
Ima im;//图像
int ih,iw;//长 宽
}hash[26];//存储图像
int len;
int dir[][2]={{0,1},{1,-1},{-1,0},{-1,-1},{0,-1},{-1,1},{1,0},{1,1}};//方向向量
Ima now;
void flood(Ima& ima,int i,int j,int cor[])//floodfill
{
ima[i][j]='0'; now[i][j]='1';
cor[0]=min(cor[0],i);
cor[1]=min(cor[1],j);
cor[2]=max(cor[2],i);
cor[3]=max(cor[3],j);
for(int k=0;k<8;k++)
{
int r,s;
r=dir[k][0]+i;
s=dir[k][1]+j;
if(r>=0 && r<h && s>=0 && s<w && ima[r][s]=='1')
flood(ima,r,s,cor);
}
}
node com;
void change()//旋转
{
Ima a;
memcpy(a,com.im,sizeof(a));
for(int i=0;i<=com.ih;i++)
for(int j=0;j<=com.iw;j++)
com.im[j][com.ih-i]=a[i][j];
swap(com.ih,com.iw);
}
void turn()//对称
{
for(int i=0;i<=com.ih/2;i++)
for(int j=0;j<=com.iw;j++)
{
char t=com.im[i][j];
com.im[i][j]=com.im[com.ih-i][j];
com.im[com.ih-i][j]=t;
}
}
bool search(int cor[])//查找星座
{
for(int r=0;r<2;r++)
{
if(r==1) turn();
for(int s=0;s<4;s++)
{
if(s!=0) change();
if(cor[2]-cor[0]!=com.ih || cor[3]-cor[1]!=com.iw) continue;
bool flag=1;
for(int i=cor[0];i<=cor[2] && flag;i++)
for(int j=cor[1];j<=cor[3] && flag;j++)
if(com.im[i-cor[0]][j-cor[1]]!=now[i][j])
{
flag=0; break;
}
if(flag==1) return 1;
}
}
return 0;
}
void insert(int cor[])//插入新星座
{
for(int i=cor[0];i<=cor[2];i++)
for(int j=cor[1];j<=cor[3];j++)
hash[len].im[i-cor[0]][j-cor[1]]=now[i][j];
hash[len].ih=cor[2]-cor[0];
hash[len].iw=cor[3]-cor[1];
}
void col(int i,int j,int c)
{
final[i][j]=(char)('a'+c);
for(int k=0;k<8;k++)
{
int r,s;
r=dir[k][0]+i; s=dir[k][1]+j;
if(r>=0 && r<h && s>=0 && s<w && final[r][s]=='1')
col(r,s,c);
}
}
void init()
{
cin>>w>>h;
for(int i=0;i<h;i++)
cin>>start[i];
len=0;
memcpy(final,start,sizeof(start));
for(int i=0;i<h;i++)
{
for(int j=0;j<w;j++)
{
if(start[i][j]=='1'){
memset(now,'0',sizeof(now));
int cor[]={INF,INF,-1,-1};//星座大小
flood(start,i,j,cor);
bool flag=0;
int k=0;
for(k;k<len;k++)
{
memcpy(com.im,hash[k].im,sizeof(com.im));
com.ih=hash[k].ih; com.iw=hash[k].iw;
if(search(cor)) {flag=1; break;}
}
if(flag==0) //查找不成功插入
{
memset(hash[len].im,'0',sizeof(start));
insert(cor);
len++;
}
col(i,j,k);//对刚才的星座染色
}
}
}
}
void outit()
{
for(int i=0;i<h;i++)
{
for(int j=0;j<w;j++)
cout<<final[i][j];
cout<<endl;
}
}
int main()
{
freopen("starry.in","r",stdin);
freopen("starry.out","w",stdout);
init();
outit();
return 0;
}