标题:磁砖样式
小明家的一面装饰墙原来是 3*10 的小方格。
现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
瓷砖只有两种颜色:黄色和橙色。
小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
小明有个小小的强迫症:忍受不了任何2*2的小格子是同一种颜色。
(瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
显然,对于 2*3 个小格子来说,口算都可以知道:一共10种贴法,如【p1.png所示】
大致思路:
有一点需要提醒,两重for循环搜到最近的一个可以落子的起点后,在执行完迭代后进行return,返回上一级;
本题的hash的方法是把每个点的颜色用0或者1进行表示,然后将这三十位变成2进制串进行联合,再转化成10进制存进set中。
刚开始错误地开了两重for循环来枚举每个点,导致搜索炸了,并出现大量的重复计算;还有,我的开始的去重方法是set<string>has;也就是把30个数按顺序存成字符串,最后加进set里面。
很努力的题解:
1 using namespace std; 2 int a[4][11]; 3 int n,m; 4 int dir[2][2]={{0,1},{1,0} }; 5 6 int is_range(int x,int y){//判断当前点在范围内返回1 7 if(x<1||x>n||y>m||y<1) 8 return 0; 9 return 1; 10 } 11 int grid(int x,int y){ 12 if(is_range(x-1,y-1)==0)return 0;//判断右下角起往左上 是否出现2*2的小格子是同一种颜色 13 int t=a[x][y]; 14 if(t!=-1&&t==a[x-1][y]&&t==a[x][y-1]&&t==a[x-1][y-1]) 15 return 1; 16 return 0; 17 } 18 set<int>has; 19 20 int gethash(int a[][11],int n,int m){//将整个图用string的“01”串进行存进来 21 int s=0; 22 for(int i=1;i<=n;i++){ 23 for(int j=1;j<=m;j++){ 24 s=(s<<1) + a[i][j]; 25 // s+=ch; 26 } 27 } 28 return s; 29 } 30 31 int ans=0; 32 int check(int i0,int j0,int i1,int j1){ 33 if(grid(i0,j0)||grid(i1,j1)) 34 return 1; 35 return 0; 36 } 37 void dfs(int i0,int j0,int i1,int j1,int step,int n,int m){//step表示本次搜索应该搜索第step块了 38 if(check(i0,j0,i1,j1)==1)//出现四块瓷砖是相同的 39 return ; 40 if(step==16){ ///搜索结束条件,全局已经铺满了15个方块数了 41 int str=gethash(a,n,m);//返回当前局面 42 if(has.count(str)==0){ 43 ans++;has.insert(str); 44 printf("**step=%d,a[]=%10d,ans=%4d\n",step,str,ans); 45 } 46 47 return ; 48 } 49 //int str=gethash(a,n,m);//返回当前局面printf(" step=%d,a[]=%10d,ans=%4d\n",step,str,ans); 50 51 for(int i=1;i<=n;i++){ 52 for(int j=1;j<=m;j++){ 53 if(a[i][j]==-1){ //该地为空 54 for(int k=0;k<=1;k++){//横着或者竖着放一块瓷砖; 55 int dx,dy; 56 dx=i+dir[k][0]; 57 dy=j+dir[k][1]; 58 if(is_range(dx,dy)==0||a[dx][dy]!=-1)continue;//越界,重复 59 for(int col=0;col<=1;col++){ //两种颜色 60 a[i][j]=a[dx][dy]=col; 61 dfs(i,j,dx,dy,step+1,n,m); 62 a[i][j]=a[dx][dy]=-1; 63 } 64 } 65 return ; 66 } 67 } 68 } 69 return ; 70 } 71 72 int main(){ 73 ans=0; 74 has.clear();//清空set 75 memset(a,-1,sizeof(a));//瓷砖黄色——值0,瓷砖橙色--1 76 // n=2;m=3; 77 n=3;m=10; 78 dfs(0,0,0,0,1,n,m); 79 printf("%d\n",ans); 80 81 return 0; 82 }
上图是n=2,m=3,(注意要在图示中的地方,step修改为4)时的结果10;——过了题目的样例;
下图是n=3,m=10,(在图示中的地方,step修改为16)时的结果,最终答案为120302。
———————所以本题我的最终答案是120302!———————————