蓝桥杯-磁砖样式 | dfs+hash

标题:磁砖样式

小明家的一面装饰墙原来是 3*10 的小方格。
现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
瓷砖只有两种颜色:黄色和橙色。
小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
小明有个小小的强迫症:忍受不了任何2*2的小格子是同一种颜色。
(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
显然,对于 2*3 个小格子来说,口算都可以知道:一共10种贴法,如【p1.png所示】
但对于 3*10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。

注意:你需要提交的是一个整数,不要填写任何多余的内容(比如:说明性文字)


思路:

看到是3*10的格子,可以考虑用dfs搜索一遍。每个格子有两种摆法,一种是横着放,一种是竖着放,两种颜色可以考虑用0,1表示,这样最后判断是否有重复的时候可以用位运算+Hash来判断。

摆放瓷砖一定要遵循一行拜访完再摆放下一行的规则,这样可以避免少考虑情况。

代码:

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <map>
#include <time.h>

using namespace std;

const int maxn=1005;
int mp[maxn][maxn];
int row,col,ans;

map<int,int> Hash;

bool check()
{
    for(int i=0;i<row;++i)
        for(int j=0;j<col;++j)
    {
        if(i+1<row&&j+1<col)
            if((mp[i][j]+mp[i+1][j]+mp[i][j+1]+mp[i+1][j+1])%4==0) return false;
    }
    return true;
}

void work(int x,int y)
{
    if(mp[x][y]==-1)
    {
        ///横放
        if(y+1<col&&mp[x][y+1]==-1)
        {
            for(int i=0;i<2;++i)
            {
                mp[x][y]=mp[x][y+1]=i;
                if(y+1<col) work(x,y+1);
                else work(x+1,0);
                mp[x][y]=mp[x][y+1]=-1;
            }
        }
        ///纵向
        if(x+1<row&&mp[x+1][y]==-1)
        {
            for(int i=0;i<2;++i)
            {
                mp[x][y]=mp[x+1][y]=i;
                if(y+1<col) work(x,y+1);
                else work(x+1,0);
                mp[x][y]=mp[x+1][y]=-1;
            }
        }
    }
    else
    {
        if(x==row-1&&y==col-1)
        {
            if(check())
            {
                int sum=0,bit=1;
                for(int i=0;i<row;++i)
                    for(int j=0;j<col;++j)
                {
                    sum+=bit*mp[i][j];
                    bit<<=1;
                }
                if(!Hash[sum])
                {
                    ans++;
                    Hash[sum]++;
                }
            }
            return;
        }
        if(y==col-1) work(x+1,0);
        else work(x,y+1);
    }
}

int main()
{
    clock_t starttime,endtime;
    while(scanf("%d%d",&row,&col)!=EOF)
    {
        //starttime=clock();
        memset(mp,-1,sizeof(mp));
        ans=0;
        work(0,0);
        //endtime=clock();
        printf("%d\n",ans);
        //printf("--%.5f\n",double(endtime-starttime)/CLOCKS_PER_SEC);
        //time=4.20300s
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/exchan/article/details/80329988