标题:磁砖样式
小明家的一面装饰墙原来是 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; }