磁砖样式——第八届蓝桥杯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:任意一个方格在其相邻的(上/下/左/右)方格至少有一个相同的数码;
代码如下:
 #include<stdio.h>
 int arr[][]={};
 int count=;
 int Judge(){
     int i=;
     int j=;
     //条件1:偶数个0和1
     int count_zero=;    //存储0/1个数
     int count_one=;
     for(i=;i<=;i++){
         for(j=;j<=;j++){
             if(arr[i][j]==){
                 count_zero++;
             }
                 else{
                     count_one++;
                 }
         }
     }
     if(count_zero%!= || count_one%!=){
         return ;
     }
     //条件2:2*2方格的数字都不相同
     int x=;
     int y=;
     for(x=;x<=;x++){    //循环至行数-1
         for(y=;y<=;y++){    //循环至列数-1
             int a=arr[x][y];
             int b=arr[x][y+];
             int c=arr[x+][y];
             int d=arr[x+][y+];
             if(a==b && a==c && a==d && b==c && b==d && c==d)
                 return ;
         }
     }
     //条件3:每个数的相邻位置要有与其相同的数
     for(i=;i<=;i++){
         for(j=;j<=;j++){
             int value=arr[i][j];
             if(i->=){    //上
                 if(value==arr[i-][j]){
                     continue;
                 }
             }
             if(i+<=){    //下
                 if(value==arr[i+][j]){
                     continue;
                 }
             }
             if(j->=){    //左
                 if(value==arr[i][j-]){
                     continue;
                 }
             }
             if(j+<=){    //右
                 if(value==arr[i][j+]){
                     continue;
                 }
                 else{    //没有相邻的数码
                     return ;
             }
             }
         }
     }
     return ;
 }
 void Style(int i,int j){    //i行、j列
     if(i== && j==){    //得到一种贴砖方式
         if(Judge()==){
         /*
             int a=0;    //输出
             int b=0;
             for(a=0;a<=1;a++){
                 for(b=0;b<=2;b++){
                     printf("%d ",arr[a][b]);
                     if(b==2){
                         printf("\n");
                     }
                 }
             }
         */
         count++;
         }
     return;
     }
     if(j==){
         i++;
         j=;
     }
     int v=;
     for(v=;v<=;v++){    //每个位置0-1循环
         arr[i][j]=v;
         Style(i,j+);
         arr[i][j]=;    //回溯
     }
 }
 int main(){
     Style(,);
     printf("%d",count);
     return ;
 }
只检验了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种贴法即可。
#include<stdio.h>
#define row 3
#define rank 10 int count=;
int arr[row+][rank+]={}; //--------------① int Judge(int x,int y){ //每一块砖的左上、右上、左下、右下四个2*2方格
if(arr[x][y]==arr[x-][y] && arr[x][y]==arr[x-][y-] && arr[x][y]==arr[x][y-]){ //左上
return ;
}
if(arr[x][y]==arr[x-][y] && arr[x][y]==arr[x-][y+] && arr[x][y]==arr[x][y+]){ //右上
return ;
}
if(arr[x][y]==arr[x][y-] && arr[x][y]==arr[x+][y-] && arr[x][y]==arr[x+][y]){ //左下
return ;
}
if(arr[x][y]==arr[x][y+] && arr[x][y]==arr[x+][y] && arr[x][y]==arr[x+][y+]){ //右下
return ;
}
return ;
} void dfs(int x,int y){
if(x== && y==){
count++;
return;
}
if(y==){
dfs(x+,);
return;
}
if(arr[x][y]==-){ //4种铺法可以任意顺序
if(arr[x][y+]==-){ // 横铺1
arr[x][y]=;
arr[x][y+]=;
if(Judge(x,y)==){
dfs(x,y+);
}
arr[x][y]=-;
arr[x][y+]=-;
}
if(arr[x+][y]==-){ // 竖铺2
arr[x][y]=;
arr[x+][y]=;
if(Judge(x,y)==){
dfs(x,y+);
}
arr[x][y]=-;
arr[x+][y]=-;
}
if(arr[x+][y]==-){ // 竖铺1
arr[x][y]=;
arr[x+][y]=;
if(Judge(x,y)==){
dfs(x,y+);
}
arr[x][y]=-;
arr[x+][y]=-;
}
if(arr[x][y+]==-){ // 横铺2
arr[x][y]=;
arr[x][y+]=;
if(Judge(x,y)==){
dfs(x,y+);
}
arr[x][y]=-;
arr[x][y+]=-;
}
} else{
dfs(x,y+);
}
} int main(){
int i=;
int j=;
for(i=;i<=;i++){ //-------------②
for(j=;j<=;j++){
arr[i][j]=-;
}
}
dfs(,);
printf("%d",count);
return ;
}
对代码中①/②的解释:
①:申请5*12的空间为方便对3*10的方格进行2*2的判断
②:只能对3*10的方格进行赋值,保证第0/4行、第0/11列(即外围一圈)的值和里面3*10的方格不同,具有很大的便利性(请大家慢慢体会)。
答案:114434
3:38:00
2018-05-07
磁砖样式——第八届蓝桥杯C语言B组(国赛)第二题的更多相关文章
- 2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告
		
2016 第七届蓝桥杯 c/c++ B组省赛真题及解题报告 勘误1:第6题第4个 if最后一个条件粗心写错了,答案应为1580. 条件应为abs(a[3]-a[7])!=1,宝宝心理苦啊.!感谢zzh ...
 - 发现环——第八届蓝桥杯C语言B组(国赛)第四题
		
原创 标题:发现环 小明的实验室有N台电脑,编号1~N.原本这N台电脑之间有N-1条数据链接相连,恰好构成一个树形网络.在树形网络上,任意两台 电脑之间有唯一的路径相连. 不过在最近一次维护网络时,管 ...
 - 希尔伯特曲线——第八届蓝桥杯C语言B组(国赛)第三题
		
原创 标题:希尔伯特曲线 希尔伯特曲线是以下一系列分形曲线 Hn 的极限.我们可以把 Hn 看作一条覆盖 2^n × 2^n 方格矩阵的曲线,曲线上一共有 2^n × 2^n 个顶点(包括左下角起点和 ...
 - 2017第八届蓝桥杯C/C++ B组省赛-日期问题
		
标题:日期问题 小明正在整理一批历史文献.这些历史文献中出现了很多日期.小明知道这些日期都在1960年1月1日至2059年12月31日.令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的 ...
 - 2017年第八届蓝桥杯C/C++B组省赛题目解析
		
一. 购物单 小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推辞. 这不,XX大促销又来了!老板夫人开出了长长的购物单,都是有打折优 ...
 - 2017第八届蓝桥杯C/C++ B组省赛-购物单
		
标题: 购物单 小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推辞. 这不,XX大促销又来了!老板夫人开出了长长的购物单,都是有打折 ...
 - 2017第八届蓝桥杯C/C++ B组省赛-等差素数列
		
标题:等差素数列 2,3,5,7,11,13,....是素数序列. 类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列. 上边的数列公差为30,长度为6. 200 ...
 - 第八届蓝桥杯C/C++ B组省赛----分巧克力
		
分巧克力 问题描述 儿童节那天有K位小朋友到小明家做客.小明拿出了珍藏的巧克力招待小朋友们. 小明一共有N块巧克力,其中第i块是Hi x Wi的方格组成的长方形. 为了公平起见,小明需要从这 N 块巧 ...
 - 【蓝桥杯】2018年第九届蓝桥杯C/C++B组省赛——B题 等差素数列
		
题目 标题:等差素数列 2,3,5,7,11,13,....是素数序列. 类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列. 上边的数列公差为30,长度为6. ...
 
随机推荐
- 在IIS上发布网站后,在编译时出现CS0016拒绝访问错误
			
错误如下图所示: 关键性错误信息: 编译器错误消息: CS0016: 未能写入输出文件“c:\Windows\Microsoft.NET\Framework64\v4.0.30319\Te ...
 - codeforces 812E Sagheer and Apple Tree(思维、nim博弈)
			
codeforces 812E Sagheer and Apple Tree 题意 一棵带点权有根树,保证所有叶子节点到根的距离同奇偶. 每次可以选择一个点,把它的点权删除x,它的某个儿子的点权增加x ...
 - unittest:2  执行多条用例,仅执行一次setUp和tearDown
			
对象方法setUp()和tearDown() 每个用例执行前后都会被调用.但是有另外一种场景:setUp之后执行完所有用例,最后调用一次tearDown.比如打开网页,多条用例分别验证网页上的元素正确 ...
 - Jarsigner签名使用
			
转载请标明出处: http://www.cnblogs.com/why168888/p/6548544.html 本文出自:[Edwin博客园] 如何签名: jarsgner-verbose-keys ...
 - python新建以时间命名的目录
			
1.新建三级目录,第一级是去年的年份,第二级是去年的月,第三级为去年的日,在日的文件中写入今年的时分秒 import os import time import shutil def create_f ...
 - 问题:从键盘读取特定类型的数据(使用Scanner读取int类型)
			
import java.util.Scanner; public class ScannerIntTest{ public static void main(String [] args){ int ...
 - background-clip 实现字体渐变效果
			
background-clip 实现字体渐变效果 (一)类似KTV字幕效果 @-webkit-keyframes loop{ 0%{background-position: -800px 0;} 10 ...
 - 软件分享:将应用一键打包成dmg文件
			
简介 苹果软件开发完成后,都要打包成dmg文件.通常的做法也许是到系统自带的磁盘工具里制作dmg文件,但这样做比较繁琐,尤其是要打包多个应用时,每次只能制作一个dmg文件很麻烦.分享一个很好用很方便的 ...
 - PHP面试系列 之框架(二)---- 常见框架的特性
			
题:PHP框架有哪些,你用过哪些?各自的优缺点是什么? 考点: (1)PHP框架的差异和优缺点 1.Yaf框架 使用PHP扩展的形式写的一个PHP框架,也就是以C语言为底层编写的,性能上要比PHP代码 ...
 - 新闻cms管理系统(一) ---- thinkphp框架准备
			
1.thinkphp介绍 一个快速.简单的基于MVC和面向对象的轻量级PHP开发框架 MVC:M数据层. V视图层 . C控制层 优点: (1)入手非常快 (2)thinkpjp提供核心内库.文件.函 ...