zoukankan      html  css  js  c++  java
  • 第八届蓝桥杯决赛 磁砖样式

    标题:磁砖样式

    小明家的一面装饰墙原来是 3*10 的小方格。
    现在手头有一批刚好能盖住2个小方格的长方形瓷砖。
    瓷砖只有两种颜色:黄色和橙色。
    小明想知道,对于这么简陋的原料,可以贴出多少种不同的花样来。
    小明有个小小的强迫症:忍受不了任何2*2的小格子是同一种颜色。
    (瓷砖不能切割,不能重叠,也不能只铺一部分。另外,只考虑组合图案,请忽略瓷砖的拼缝)
    显然,对于 2*3 个小格子来说,口算都可以知道:一共10种贴法,如【p1.png所示】
    但对于 3*10 的格子呢?肯定是个不小的数目,请你利用计算机的威力算出该数字。

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

    样例


    思路

      去年比赛时被这题坑了,一直想用轮廓线动态规划去做。。。其实直接暴力搜索就可以。

      依次枚举每一个格子,每摆放满一行,再尝试去摆放下一行。在位置$(x,y)$处有两种摆放方式:横向和纵向。

      当摆满所有格子的时候就检查是否出现某个2*2的小格子是同一种颜色,以及这种摆放方式是否已经计算过。我是采用二进制来表示每一种能铺满的情况,黄色用0表示,橙色用1表示,再用map来记录和判断是否重复计算。


    详细代码

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <map>
     4 #include <algorithm>
     5 using namespace std;
     6 const int w = 3, h = 10;
     7 int graph[w][h];
     8 int ans = 0;
     9 
    10 map<int, int> Hash;
    11 
    12 //检查2x2格子颜色是否相同
    13 bool check_color() {
    14     for(int i = 0; i < w; i++) 
    15     for(int j = 0; j < h; j++) {
    16         if(i+1 < w && j+1 < h) {
    17             if((graph[i][j]+graph[i][j+1]+graph[i+1][j]+graph[i+1][j+1]) % 4 == 0) 
    18                 return false;
    19         }
    20     }
    21     return true;
    22 }
    23 
    24 void fill_with_tile(int x, int y) {
    25     if(graph[x][y] == -1) {
    26         //横向摆放
    27         if(y+1 < h && graph[x][y+1] == -1) {
    28 
    29             for(int i = 0; i < 2; i++) {
    30                 graph[x][y] = graph[x][y+1] = i;
    31                 if(y == h-1) {  //铺下一行
    32                     fill_with_tile(x+1, 0);
    33                 } else {        //铺当前行的下一个格子
    34                     fill_with_tile(x, y+1);
    35                 }
    36                 graph[x][y] = graph[x][y+1] = -1;
    37             }
    38 
    39         }
    40         //纵向摆放
    41         if(x+1 < w && graph[x+1][y] == -1) {
    42             for(int i = 0; i < 2; i++) {
    43                 graph[x][y] = graph[x+1][y] = i;
    44                 if(y == h-1) {  //铺下一行
    45                     fill_with_tile(x+1, 0);
    46                 } else {        //铺当前行的下一个格子
    47                     fill_with_tile(x, y+1);
    48                 }
    49                 graph[x][y] = graph[x+1][y] = -1;
    50             }
    51         }
    52     } else {
    53         if(x == w-1 && y == h-1) { //成功铺满
    54             if(check_color()) {
    55                 //判断是否出现重复情况
    56                 int ret = 0, bit = 1;
    57                 for(int i = 0; i < w; i++)
    58                 for(int j = 0; j < h; j++) {
    59                     ret += graph[i][j] * bit;
    60                     bit *= 2;
    61                 }
    62                 if(!Hash.count(ret)) {
    63                     Hash[ret] = 1;
    64                     ans++;
    65                 }
    66             }
    67             return;
    68         }
    69         if(y == h-1) {          //铺下一行
    70             fill_with_tile(x+1, 0);
    71         } else {                //铺当前行的下一个格子
    72             fill_with_tile(x, y+1);
    73         }
    74     }
    75 }
    76 
    77 int main() {
    78     memset(graph, -1, sizeof(graph));
    79     fill_with_tile(0, 0);
    80     printf("%d
    ", ans);
    81     return 0;
    82 }

    只需要1s就算出来答案了,合理的铺放方式共有101466种。


    如有不当之处欢迎指出!

  • 相关阅读:
    Azure PowerShell (2) 修改Azure订阅名称
    Windows Azure Platform Introduction (11) 了解Org ID、Windows Azure订阅、账户
    Azure PowerShell (3) 上传证书
    Azure PowerShell (1) PowerShell入门
    Windows Azure Service Bus (2) 队列(Queue)入门
    Windows Azure Service Bus (1) 基础
    Windows Azure Cloud Service (10) Role的生命周期
    Windows Azure Cloud Service (36) 在Azure Cloud Service配置SSL证书
    Android studio 使用心得(一)—android studio快速掌握快捷键
    android 签名、混淆打包
  • 原文地址:https://www.cnblogs.com/flyawayl/p/8503152.html
Copyright © 2011-2022 走看看