思路:
当摆满所有格子的时候就检查是否出现某个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;
}