zoukankan      html  css  js  c++  java
  • 第八届蓝桥杯C/C++程序设计本科B组决赛 ——瓷砖样式(填空题)【DP?我的暴力排列搜索】

    标题:磁砖样式
    小明家的一面装饰墙原来是 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
    ",step,str,ans);
    45         }
    46 
    47         return ;
    48     }
    49       //int str=gethash(a,n,m);//返回当前局面printf("  step=%d,a[]=%10d,ans=%4d
    ",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
    ",ans);
    80 
    81     return 0;
    82 }
    View Code(代码有详细注释)

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

     

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

     
  • 相关阅读:
    sublime text 4 vim 插件配置
    ssh-keygen 的使用
    distribution transaction solution
    bilibili 大数据 视频下载 you-get
    Deepin 20.2.1 安装 MS SQL 2019 容器版本
    【转】使用Linux下Docker部署MSSQL并加载主机目录下的数据库
    【转】You Can Now Use OneDrive in Linux Natively Thanks to Insync
    dotnet 诊断工具安装命令
    Linux 使用 xrandr 设置屏幕分辨率
    【转】CentOS 7.9 2009 ISO 官方原版镜像下载
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/9046132.html
Copyright © 2011-2022 走看看