1347: [蓝桥杯2017决赛]磁砖样式

在这里插入图片描述
思路:
当摆满所有格子的时候就检查是否出现某个2*2的小格子是同一种颜色,以及这种摆放方式是否已经计算过。我是采用二进制来表示每一种能铺满的情况,黄色用0表示,橙色用1表示,再用map来记录和判断是否重复计算。

看代码,有很详细的注释!!!

#include<bits/stdc++.h>
using namespace std;
#define ll long long
map<int,int>mp;
int graph[4][11]; ///
int ans=0;
bool check()///检查2x2格子颜色是否相同
{
    int cnt=0;
    for(int i=1; i<=3; i++)
    {
        for(int j=1; j<=10; j++)
        {
            if(i+1<=3&&j+1<=10)
            {
                cnt=graph[i][j]+graph[i][j+1]+graph[i+1][j]+graph[i+1][j+1];
                if(cnt%4==0) return 0;
            }

        }
    }
    return 1;
}

///需要注意的是一块地板占两格

///黄色用0表示,橙色用1表示
void fill_with_tile(int x,int y)
{
    if(graph[x][y]==-1)
    {
        if(graph[x][y+1]==-1&&y+1<=10)///横着铺
        {
            for(int i=0; i<2; i++)
            {
                graph[x][y]=i;
                graph[x][y+1]=i;
                ///横着铺的时候不需要考虑换行的问题,如果这一行铺满了
                ///那么就不符合if的条件了
                ///所以会直接换成竖着铺(进入下一个if)

                fill_with_tile(x,y+1);

                graph[x][y]=-1;///回溯
                graph[x][y+1]=-1;
            }
        }
        if(graph[x+1][y]==-1&&x+1<=3) ///竖着铺
        {
            for(int i=0; i<2; i++)
            {
                graph[x][y]=i;
                graph[x+1][y]=i;

                if(y==10)
                {
                    fill_with_tile(x+1,1);
                }
                else
                {
                    fill_with_tile(x,y+1);
                }
                graph[x][y]=-1;
                graph[x+1][y]=-1;
            }
        }
    }
    else
    {
        if(x==3&&y==10)
        {
            if(check())///检查是否有2*2格子颜色相同的情况
            {
                int cnt=0;
                int bit=1;
                for(int i=1; i<=3; i++)///将每一次的结果转化为二进制形式,以达到去重的目的
                {
                    for(int j=1; j<=10; j++)
                    {
                        cnt+=graph[i][j]*bit;
                        bit=bit*2;
                    }
                }
                if(mp[cnt]==0)
                {
                    mp[cnt]=1;
                    ans++;
                }
            }
        }
        else
        {
            if(y==10)
            {
                fill_with_tile(x+1,1);
            }
            else fill_with_tile(x,y+1);
        }
    }
}
int main()
{
    ios::sync_with_stdio(false); 
    memset(graph,-1,sizeof(graph));///全部初始化为-1
    fill_with_tile(1,1);;///从1,1开始铺
    cout<<ans<<endl;
//    cout<<101466<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值