sgu-243 Broken Chessboard

59 篇文章 1 订阅
2 篇文章 0 订阅
题目大意:

给你一个 2020 的桌面,上面有一些用不同字母标号的联通块,联通块可以旋转 90,180,270 度,(为’.’则表示是桌子)。已知这些联通块是由一个 NN,(N<=5) 的网格拆开得到的,要你求出一种拼接方案拼出 NN 的网格。

解题思路:

首先我们看到这么小的 N ,明显是暴力。
然后就是如何暴力了。
首先我们先处理出每一个联通块,并且求出每个联通块旋转可以得到的所有联通块(要去重,不然会TLE)。可以用hash去重。
然后我们将所有的联通块按大小排序,从大到小暴力枚举就行了。

AC代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int Mod=3307;

struct GG_
{
    int G[7][7];
    int Si[2];
    char le;
    int SS;
}GG[1000]={{{{0}},0,'\0'}};

int N;
char ch[30][30]={"\0"};
char help[30][30]={"\0"};
int hash[30][30]={{0}};
int Gp=0;
int go[5][2]={{0,1},{0,-1},{1,0},{-1,0}};
int Minx=2e9,Maxx=-2e9,Miny=2e9,Maxy=-2e9;
bool exist[27][6][6][3320];
char ans[10][10]={"\0"};
int num=0;
bool Ok[30]={0};
int st[30]={0};
int stp=0;

bool cmp(struct GG_ a1,struct GG_ a2)
{return a1.SS>a2.SS || (a1.SS==a2.SS && a1.le<a2.le);}

inline void dfs(int xx,int yy)
{
    GG[Gp].SS++;
    Minx=min(xx,Minx);Miny=min(yy,Miny);
    Maxx=max(xx,Maxx);Maxy=max(yy,Maxy);
    hash[xx][yy]=1;
    for(register int i=0;i<4;i++)
    {
        int xxx=xx+go[i][0],yyy=yy+go[i][1];
        if(xxx>=1 && xxx<=20 && yyy>=1 && yyy<=20 && hash[xxx][yyy]==0)
            if(ch[xx][yy]==ch[xxx][yyy])
                dfs(xxx,yyy);
    }
    return;
}

void Find()
{
    for(register int i=1;i<=20;i++)
        for(register int j=1;j<=20;j++)
        {
            if(hash[i][j]==1) continue;
            if(ch[i][j]!='.')
            {
                Minx=2e9,Maxx=-2e9,Miny=2e9,Maxy=-2e9;
                Gp++;
                dfs(i,j);
                int hh=0;
                for(register int xx=Minx;xx<=Maxx;xx++)
                {
                    for(register int yy=Miny;yy<=Maxy;yy++)
                    {
                        hh=hh*10%Mod;
                        if(ch[xx][yy]==ch[i][j])
                        {
                            hh=(hh+1)%Mod;
                            GG[Gp].G[xx-Minx+1][yy-Miny+1]=1;
                        }
                    }
                    hh=(hh*10+9)%Mod;
                }
                if(exist[ch[i][j]-'A'+1][Maxx-Minx+1][Maxy-Miny+1][hh]==0)
                {
                    exist[ch[i][j]-'A'+1][Maxx-Minx+1][Maxy-Miny+1][hh]=1;
                    GG[Gp].Si[0]=Maxx-Minx+1;GG[Gp].Si[1]=Maxy-Miny+1;
                    GG[Gp].le=ch[i][j];
                }
                else
                {
                    memset(GG[Gp].G,0,sizeof(GG[Gp].G));
                    GG[Gp].SS=0;
                    Gp--;
                }
            }
        }
    return;
}

inline bool check(int i,int j,int p)
{
    for(register int xx=1;xx<=GG[p].Si[0];xx++)
        for(register int yy=1;yy<=GG[p].Si[1];yy++)
            if(GG[p].G[xx][yy]==1 && ans[i+xx-1][j+yy-1]!='\0')
                return false;
    return true;
}

inline void change(int i,int j,int p,char C,int Add)
{
    for(register int xx=1;xx<=GG[p].Si[0];xx++)
        for(register int yy=1;yy<=GG[p].Si[1];yy++)
            if(GG[p].G[xx][yy]==1)
                ans[i+xx-1][j+yy-1]=C,num+=Add;
    return;
}

inline void get_ans(int now)
{
    if(num==N*N)
    {
        for(register int i=1;i<=N;i++)
            puts(ans[i]+1);
        exit(0);
    }
    if(now>stp) return;
    for(int p=st[now];p<st[now+1];p++)
    {
        if(Ok[GG[p].le-'A'+1]==1) continue;
        for(register int i=1;i<=N;i++)
        {
            if(i+GG[p].Si[0]-1>N) break;
            for(register int j=1;j<=N;j++)
            {
                if(j+GG[p].Si[1]-1>N) break;
                if(check(i,j,p)==true)
                {
                    Ok[GG[p].le-'A'+1]=1;
                    change(i,j,p,GG[p].le,1);
                    get_ans(now+1);
                    change(i,j,p,'\0',-1);
                    Ok[GG[p].le-'A'+1]=0;
                }
            }
        }
    }
    return;
}

int main()
{
    scanf("%d\n",&N);
    for(int i=1;i<=20;i++)
        scanf("%s",ch[i]+1);
    Find();
    for(register int i=1;i<=3;i++)
    {
        memset(hash,0,sizeof(hash));
        for(register int i=1;i<=20;i++)
            for(register int j=1;j<=20;j++)
                help[j][20-i+1]=ch[i][j];
        memcpy(ch,help,sizeof(ch));
        Find();
    }
    sort(GG+1,GG+Gp+1,cmp);
    for(int i=1;i<=Gp;i++)
    {
        if(GG[i].le!=GG[i-1].le)
        {
            stp++;
            st[stp]=i;
        }
    }
    st[stp+1]=Gp+1;
    get_ans(1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值