第八届蓝桥杯C/C++程序设计本科B组决赛 ——瓷砖样式(填空题)

标题:磁砖样式
小明家的一面装饰墙原来是 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 }
View Code(代码有详细注释)

上图是n=2,m=3,(注意要在图示中的地方,step修改为4)时的结果10;——过了题目的样例;
下图是n=3,m=10,(在图示中的地方,step修改为16)时的结果,最终答案为120300。

 

———————所以本题我的最终答案是120302!———————————

扫描二维码关注公众号,回复: 869595 查看本文章
 

猜你喜欢

转载自www.cnblogs.com/zhazhaacmer/p/9046132.html