Description
高高的星空,簇簇闪耀的群星形态万千。一个星座(cluster)是一群连通的星组成的非空集合,所谓连通是指水平,垂直或者对角相邻。一个星座不能是另一个更大星座的一部分。星座可以相似(similar)。如果两个星座有相同的形状,而且包括相同数目的星体,那么不管其方向性如何,就算相似。一般而言,星座可能的方向有八个,如图1所示。
图1 相似的八个星座
Input
夜空可以表示为一份天体图(sky map),它是一个由字符0和1组成的二维矩阵,字符1表示所在的位置有一颗星;字符0表示该位置上没有星。任务给定一份天体图,用同一个小写英文标识(mark)相似的所有星座。相似的星座必须用相同的字母标识,不同的星座表示为不同的字母。标识一个星座,就是将其中各星体对应的字符1替换为相应的小写字母。
文件的前两行分别记录了天体图的宽度W、深度H。而天体图则是由接下来的H行表示,每行包括W个字符。
Output
输出文件记录了天体图与文件STARRY.IN相似,不同之处在于,各个星座按照“任务”中的要求进行了标识(mark)。
Constraints
0 <= W (天体图的宽度) <= 100
0 <= H (天体图的深度) <= 100
0 <= 星座的数目 <= 500
0 <= 不相似的星座数目 <= 26 (a..z)
1 <= 各星座包含的星体数目 <= 160
Analsis
我又双叒叕被usaco恶心到了
无视上面那句话好了
先是bfs找到所有的连通块并标号,记录最上最下最左最右
然后就是枚举两个星座看它们是否相同。怎么做呢?暴力枚举八种转法,然后暴力比较就可以了。如果找到两个相同的星座,就将他们在并查集中合并
优化::
如果不加优化是不能过的,所以考虑怎么卡过去
一个可行的优化是每次只找并查集中的根节点与其他星座比较,这样可以减少不必要的比较次数
还有就是星星数目不相同的星座一定不相同,这点很重要
Code
/*
ID:wjp13241
PROG:starry
LANG:C++
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <stack>
#include <queue>
#define fo(i,a,b) for (int i=a;i<=b;i++)
#define fil(x,t) memset(x,t,sizeof(x))
#define STP system("pause")
#define min(x,y) x<y?x:y
#define max(x,y) x>y?x:y
#define ld long double
#define ll long long
#define INF 0x3f3f3f3f
#define EPS 1e-4
#define N 101
#define E 501
using namespace std;
struct pos{
int x,y;
pos operator +(const pos &b)const{return (pos){x+b.x,y+b.y};}
}dir[8]={{-1,0},{1,0},{0,-1},{0,1},{-1,-1},{-1,1},{1,-1},{1,1}};
struct cstl{int u,d,l,r,cnt;}c[E];
struct grap{int map[N][N],n,m;};
int map[N][N],fld[N][N],id[E],f[E];
int swap(int &x,int &y){x^=y;y^=x;x^=y;}
int find(int x)
{
if (f[x]==x)
return x;
f[x]=find(f[x]);
return f[x];
}
int merge(int x,int y)
{
if (find(y)!=find(x))
f[find(y)]=find(x);
}
bool check(grap a,grap b)
{
if (a.n!=b.n||a.m!=b.m)
return false;
fo(i,1,a.n)
fo(j,1,a.m)
if (a.map[i][j]!=b.map[i][j])
return false;
return true;
}
int bfs(pos st,int cnt)
{
fld[st.x][st.y]=cnt;
queue<pos>q;
q.push(st);
while (!q.empty())
{
pos now=q.front();q.pop();
c[cnt]=(cstl){min(c[cnt].u,now.x),max(c[cnt].d,now.x),min(c[cnt].l,now.y),max(c[cnt].r,now.y),c[cnt].cnt+1};
fo(i,0,7)
{
pos tmp=now+dir[i];
if (map[tmp.x][tmp.y]&&!fld[tmp.x][tmp.y])
{
fld[tmp.x][tmp.y]=cnt;
q.push(tmp);
}
}
}
}
int main()
{
freopen("starry.in","r",stdin);
freopen("starry.out","w",stdout);
fo(i,1,E-1)
{
c[i]=(cstl){INF,0,INF,0,0};
f[i]=i;
}
int n,m;
scanf("%d%d",&m,&n);
fo(i,1,n)
{
char s[N];
scanf("%s",s);
fo(j,1,m)
map[i][j]=s[j-1]-'0';
}
int cnt=0;
fo(i,1,n)
fo(j,1,m)
if (map[i][j]&&!fld[i][j])
bfs((pos){i,j},++cnt);
fo(a,1,cnt)
if (find(a)==a)
fo(b,a+1,cnt)
if (c[a].cnt==c[b].cnt&&find(a)!=find(b))
{
grap A={{},0,0},B={{},0,0};
A.n=c[a].d-c[a].u+1;
A.m=c[a].r-c[a].l+1;
fo(i,c[a].u,c[a].d)
fo(j,c[a].l,c[a].r)
if (fld[i][j]==a)
A.map[i-c[a].u+1][j-c[a].l+1]=1;
B.n=c[b].d-c[b].u+1;
B.m=c[b].r-c[b].l+1;
fo(i,c[b].u,c[b].d)
fo(j,c[b].l,c[b].r)
if (fld[i][j]==b)
B.map[i-c[b].u+1][j-c[b].l+1]=1;
bool flag=false;
grap tmpA=A;
grap bak=A;
if (check(tmpA,B))
{
merge(a,b);
flag=true;
}
if (!flag)
{
bak=tmpA;
fil(tmpA.map,0);
fo(i,1,bak.n)
fo(j,1,bak.m)
tmpA.map[j][bak.n-i+1]=bak.map[i][j];
swap(tmpA.n,tmpA.m);
if (check(tmpA,B))
{
merge(a,b);
flag=true;
}
}
if (!flag)
{
bak=tmpA;
fil(tmpA.map,0);
fo(i,1,bak.n)
fo(j,1,bak.m)
tmpA.map[j][bak.n-i+1]=bak.map[i][j];
swap(tmpA.n,tmpA.m);
if (check(tmpA,B))
{
merge(a,b);
flag=true;
}
}
if (!flag)
{
bak=tmpA;
fil(tmpA.map,0);
fo(i,1,bak.n)
fo(j,1,bak.m)
tmpA.map[j][bak.n-i+1]=bak.map[i][j];
swap(tmpA.n,tmpA.m);
if (check(tmpA,B))
{
merge(a,b);
flag=true;
}
}
if (!flag)
{
bak=A;
fil(tmpA.map,0);
fo(i,1,bak.n)
fo(j,1,bak.m)
tmpA.map[i][bak.m-j+1]=bak.map[i][j];
swap(tmpA.n,tmpA.m);
if (check(tmpA,B))
{
merge(a,b);
flag=true;
}
}
if (!flag)
{
bak=tmpA;
fil(tmpA.map,0);
fo(i,1,bak.n)
fo(j,1,bak.m)
tmpA.map[j][bak.n-i+1]=bak.map[i][j];
swap(tmpA.n,tmpA.m);
if (check(tmpA,B))
{
merge(a,b);
flag=true;
}
}
if (!flag)
{
bak=tmpA;
fil(tmpA.map,0);
fo(i,1,bak.n)
fo(j,1,bak.m)
tmpA.map[j][bak.n-i+1]=bak.map[i][j];
swap(tmpA.n,tmpA.m);
if (check(tmpA,B))
{
merge(a,b);
flag=true;
}
}
}
int num=0;
fo(i,1,cnt)
if (!id[find(i)])
id[find(i)]=++num;
fo(i,1,n)
{
fo(j,1,m)
if (map[i][j])
printf("%c",(char)(id[find(fld[i][j])]-1+'a'));
else
printf("0");
printf("\n");
}
return 0;
}