Starry Night_usaco 5.1_bfs+暴力

66 篇文章 0 订阅
53 篇文章 0 订阅

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;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值