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!———————————

     
  • 相关阅读:
    SQL数据库常用命令
    软件测试基础学习
    单链表面试题集合
    常见算法排序,冒泡排序,快排,堆排,归并排序
    CSS学习笔记(2)
    CSS学习笔记(1)
    sublime快捷键
    Sublime Text 中文输入法无法跟随怎么办
    网站收集
    Centos7安装Jenkins
  • 原文地址:https://www.cnblogs.com/zhazhaacmer/p/9046132.html
Copyright © 2011-2022 走看看