蓝桥杯 2017第八届国赛c/c++b组第2题 磁砖样式
程序员文章站
2024-02-10 16:08:52
...
/*
标题:磁砖样式
小明家的一面装饰墙原来是 3*10 的小方格。
现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
瓷砖只有两种颜色:黄色和橙色。
小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
小明有个小小的强迫症:忍受不了任何22的小格子是同一种颜色。
(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
显然,对于 23 个小格子来说,口算都可以知道:一共10种贴法,如【p1.png所示】
但对于 3*10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。
注意:你需要提交的是一个整数,不要填写任何多余的内容(比如:说明性文字)
分析:
从第一行第一列开始贴,
如果贴过了递归到该行下一列
如果越界了递归到下一行第一列
有四种可能:横着贴黄色或橙色;竖着贴黄色和橙色,题目里用0和1表示
贴完后(递归边界):
1.判断2*2的小格子是否是同一种颜色
2.检查是否重复
3.ans++
*/
#include<iostream>
#include<map>
#include<cstring>
using namespace std;
typedef long long int ll;
int a[5][12],n,m,ans;
map<ll,ll>check;
bool judge() //judge:判断2*2的小格子是否是同一种颜色
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(a[i][j]==a[i][j+1]&&a[i][j]==a[i+1][j]&&a[i][j]==a[i+1][j+1])
return false;
}
return true;
}
bool check_() //判断有没有重复
{
int s=0,bit=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
s+=a[i][j]*bit;
bit*=2;
}
if(check[s]==0)
{
check[s]=1;
return true;
}
return false;
}
void dfs(int x,int y)
{
if(x==n+1)
{
if(judge()&&check_())
{
ans++;
}
return;
}
if(a[x][y]==-1) //判断该位置是否贴过瓷砖,贴过了y+1
{
if(y<m+1) //判断该位置是否越界,越界了dfs(x+1,1)
{
if(y<m&&a[x][y+1]==-1)//横着放1或0
{
a[x][y]=a[x][y+1]=1;
dfs(x,y+2);
a[x][y]=a[x][y+1]=0;
dfs(x,y+2);
a[x][y]=a[x][y+1]=-1;
}
if(x<n&&a[x+1][y]==-1)//竖着放1或0
{
a[x][y]=a[x+1][y]=1;
dfs(x,y+1);
a[x][y]=a[x+1][y]=0;
dfs(x,y+1);
a[x][y]=a[x+1][y]=-1;
}
}
else
dfs(x+1,1);
}
else
dfs(x,y+1);
}
int main()
{
cin>>n>>m;
memset(a,-1,sizeof(a));
dfs(1,1);
cout<<ans<<endl;
// cout<<check.size()<<endl;
return 0;
}
上一篇: 使用和学习PHP有多难