蓝桥杯 2017第八届国赛c/c++b组第2题 磁砖样式

/*

标题:磁砖样式

小明家的一面装饰墙原来是 3*10 的小方格。
现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
瓷砖只有两种颜色:黄色和橙色。

小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
小明有个小小的强迫症:忍受不了任何22的小格子是同一种颜色。
(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
显然,对于 2
3 个小格子来说,口算都可以知道:一共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; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值