蓝桥杯2017国赛 瓷砖样式 dfs+hush

小明家的一面装饰墙原来是 3*10 的小方格。

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

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


这题由于有一个坑,只考虑组合图案,不考虑缝隙,就会产生重复。比如一个


所以使用hush来去重,而且我发现我的dfs好像还是有一点不熟练。。。

#include <iostream>
#include<cstring>
#include<map>
#define LL long long
using namespace std;
int mp[10][20];
map<LL ,LL> hush;
int m,n,ans = 0;
bool judge(){
    for(int i =0;i<n-1;i++){
        for(int j=0;j<m-1;j++){
            if(mp[i][j] == 0 || mp[i+1][j+1] == 0)
                return false;
            int tmp = mp[i][j];
            if(tmp == mp[i+1][j] && tmp == mp[i][j+1] && tmp == mp[i+1][j+1])
                return false;
        }
    }
    return true;
}
void show(){
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cout<<mp[i][j]<<' ';
        }
        cout<<endl;
    }
    cout<<endl;
}
void dfs(int x,int y){
    if(y >= m){
        dfs(x+1,0);
        return;
    }
    if(mp[x][y]){
        dfs(x,y+1);
        return;
    }
    if(x == n){
        if(judge()){
            LL sum = 0;
            LL bits = 1;
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    sum+=mp[i][j] * bits;
                    bits <<= 1;
                }
            }
            if(hush[sum] == 0){
                hush[sum] = 1;
                ans++;
            }
        }
        return;
    }
    if(y+1 < m && mp[x][y+1] == 0 && mp[x][y] == 0){
        mp[x][y+1] = 1;
        mp[x][y] = 1;
        dfs(x,y+1);
        mp[x][y+1] = 2;
        mp[x][y] = 2;
        dfs(x,y+1);
        mp[x][y+1] = 0;
        mp[x][y] = 0;
    }
    if(x+1 < n && mp[x+1][y] == 0 && mp[x][y] == 0){
        mp[x+1][y] = 1;
        mp[x][y] = 1;
        dfs(x,y+1);
        mp[x+1][y] = 2;
        mp[x][y] = 2;
        dfs(x,y+1);
        mp[x+1][y] = 0;
        mp[x][y] = 0;
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n>>m;
    dfs(0,0);
    cout<<ans<<endl;
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值