zoukankan      html  css  js  c++  java
  • 磁砖样式——第八届蓝桥杯C语言B组(国赛)第二题

    原创


    标题:磁砖样式

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

    小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
    小明有个小小的强迫症:忍受不了任何2*2的小格子是同一种颜色。
    (瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
    显然,对于 2*3 个小格子来说,口算都可以知道:一共10种贴法,如【p1.png所示】

    但对于 3*10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。

    注意:你需要提交的是一个整数,不要填写任何多余的内容(比如:说明性文字)

    一开始的想法是在数组里面枚举出全部的情况组合,比如2*3的方格,用0/1代表两种颜色;

    那么一共会有pow(2,6)=64种情况,然后用3个判断条件筛选出符合要求的贴砖方式:

    1:   数码0/1有偶数个;

    2:任意2*2的方格的数码不能相同;

    3:任意一个方格在其相邻的(上/下/左/右)方格至少有一个相同的数码;

    代码如下:

      1 #include<stdio.h>
      2 
      3 int arr[3][6]={0};
      4 int count=0;
      5 
      6 int Judge(){
      7     int i=0;
      8     int j=0;
      9     //条件1:偶数个0和1    
     10     int count_zero=0;    //存储0/1个数 
     11     int count_one=0;
     12     for(i=0;i<=2;i++){
     13         for(j=0;j<=5;j++){
     14             if(arr[i][j]==0){
     15                 count_zero++;
     16             }
     17                 else{
     18                     count_one++;
     19                 }
     20         }
     21     }
     22     if(count_zero%2!=0 || count_one%2!=0){
     23         return 0;
     24     }
     25     //条件2:2*2方格的数字都不相同
     26     int x=0;
     27     int y=0;
     28     for(x=0;x<=1;x++){    //循环至行数-1 
     29         for(y=0;y<=4;y++){    //循环至列数-1 
     30             int a=arr[x][y];
     31             int b=arr[x][y+1];
     32             int c=arr[x+1][y];
     33             int d=arr[x+1][y+1];
     34             if(a==b && a==c && a==d && b==c && b==d && c==d)
     35                 return 0;
     36         }
     37     }
     38     //条件3:每个数的相邻位置要有与其相同的数
     39     for(i=0;i<=2;i++){
     40         for(j=0;j<=5;j++){
     41             int value=arr[i][j];
     42             if(i-1>=0){    //
     43                 if(value==arr[i-1][j]){
     44                     continue;
     45                 }
     46             } 
     47             if(i+1<=1){    //
     48                 if(value==arr[i+1][j]){
     49                     continue;
     50                 }        
     51             }
     52             if(j-1>=0){    //
     53                 if(value==arr[i][j-1]){
     54                     continue;
     55                 }
     56             } 
     57             if(j+1<=2){    //
     58                 if(value==arr[i][j+1]){
     59                     continue;
     60                 }
     61                 else{    //没有相邻的数码 
     62                     return 0;
     63             }
     64             }
     65         }
     66     }
     67     return 1;
     68 }
     69 
     70 void Style(int i,int j){    //i行、j列
     71 
     72     if(i==2 && j==6){    //得到一种贴砖方式
     73     
     74         if(Judge()==1){
     75         /*
     76             int a=0;    //输出
     77             int b=0;
     78             for(a=0;a<=1;a++){
     79                 for(b=0;b<=2;b++){
     80                     printf("%d ",arr[a][b]);
     81                     if(b==2){
     82                         printf("
    ");
     83                     }
     84                 }
     85             }
     86         */
     87         count++;
     88         }
     89     return;
     90     }
     91 
     92     if(j==6){
     93         i++;
     94         j=0;
     95     }
     96     int v=0;
     97     for(v=0;v<=1;v++){    //每个位置0-1循环
     98         arr[i][j]=v;
     99         Style(i,j+1);
    100         arr[i][j]=0;    //回溯
    101     }
    102 }
    103 
    104 int main(){
    105     Style(0,0);
    106     printf("%d",count);
    107     return 0;
    108 }

    只检验了2*3、3*6的方格的样例,2*3的样例输出了正确的答案,3*6的输出错误。

    3*10的数据量太大跑不出来了。

    上面的3个控制条件太少,像

    1 0 1 1 0 0

    1 1 0 0 0 1

    1 0 1 1 0 1

    这样的贴砖方式能通过条件但却是不符合要求的,因为这种方式太过于暴力,所以没有继续改进。

    此题应该通过DFS解决:

    3*10的方格,每个空方格都可以有4种贴法:(我们以1/2号定义两种颜色的砖)

    横着贴1号砖、横着贴2号砖、竖着贴1号砖、竖着贴2号砖

    所以我们用DFS搜索每块空砖的这4种贴法即可。

     1 #include<stdio.h>
     2 #define row 3
     3 #define rank 10
     4 
     5 int count=0;
     6 int arr[row+2][rank+2]={0};    //--------------① 
     7 
     8 int Judge(int x,int y){    //每一块砖的左上、右上、左下、右下四个2*2方格 
     9     if(arr[x][y]==arr[x-1][y] && arr[x][y]==arr[x-1][y-1] && arr[x][y]==arr[x][y-1]){    //左上
    10         return 0;
    11     } 
    12     if(arr[x][y]==arr[x-1][y] && arr[x][y]==arr[x-1][y+1] && arr[x][y]==arr[x][y+1]){    //右上
    13         return 0;
    14     }
    15     if(arr[x][y]==arr[x][y-1] && arr[x][y]==arr[x+1][y-1] && arr[x][y]==arr[x+1][y]){    //左下
    16         return 0;
    17     }
    18     if(arr[x][y]==arr[x][y+1] && arr[x][y]==arr[x+1][y] && arr[x][y]==arr[x+1][y+1]){    //右下
    19         return 0;
    20     }
    21     return 1;
    22 }
    23 
    24 void dfs(int x,int y){
    25     if(x==3 && y==11){
    26         count++;
    27         return;
    28     }
    29     if(y==11){
    30         dfs(x+1,1);
    31         return;
    32     }
    33     if(arr[x][y]==-1){    //4种铺法可以任意顺序 
    34         if(arr[x][y+1]==-1){    //    横铺1
    35             arr[x][y]=1;
    36             arr[x][y+1]=1;
    37             if(Judge(x,y)==1){
    38                 dfs(x,y+1);
    39             }
    40             arr[x][y]=-1;
    41             arr[x][y+1]=-1;
    42         } 
    43         if(arr[x+1][y]==-1){    //    竖铺2
    44             arr[x][y]=2;
    45             arr[x+1][y]=2;
    46             if(Judge(x,y)==1){
    47                 dfs(x,y+1);
    48             }
    49             arr[x][y]=-1;
    50             arr[x+1][y]=-1; 
    51         }
    52         if(arr[x+1][y]==-1){    //    竖铺1
    53             arr[x][y]=1;
    54             arr[x+1][y]=1;
    55             if(Judge(x,y)==1){
    56                 dfs(x,y+1);
    57             }
    58             arr[x][y]=-1;
    59             arr[x+1][y]=-1;
    60         }
    61         if(arr[x][y+1]==-1){    //    横铺2
    62             arr[x][y]=2;
    63             arr[x][y+1]=2;
    64             if(Judge(x,y)==1){
    65                 dfs(x,y+1);
    66             }
    67             arr[x][y]=-1;
    68             arr[x][y+1]=-1;
    69         }
    70     }
    71     
    72     else{
    73         dfs(x,y+1);
    74     }
    75 }
    76 
    77 int main(){
    78     int i=0;
    79     int j=0;
    80     for(i=1;i<=3;i++){    //-------------② 
    81         for(j=1;j<=10;j++){
    82             arr[i][j]=-1;
    83         }
    84     }
    85     dfs(1,1);
    86     printf("%d",count);
    87     return 0;
    88 }

    对代码中①/②的解释:

    ①:申请5*12的空间为方便对3*10的方格进行2*2的判断

    ②:只能对3*10的方格进行赋值,保证第0/4行、第0/11列(即外围一圈)的值和里面3*10的方格不同,具有很大的便利性(请大家慢慢体会)。

    答案:114434

    3:38:00

    2018-05-07

  • 相关阅读:
    Mybatis 传入的参数为List
    IDEA 自动清除不使用的 引用包
    java List去除重复数据
    oracle 导出数据库报错 EXP-00002: 写入导出文件时出错 EXP-00000: 导出终止失败
    Tomcat修改窗口名
    Oracle忘记密码找回
    3springboot执行原理及自动装配原理
    2springboot第一个程序
    springboot项目有红叉,但是没有运行没有报错。
    1springboot与微服务
  • 原文地址:https://www.cnblogs.com/chiweiming/p/8992262.html
Copyright © 2011-2022 走看看