蓝桥杯,考暴力和搜索,这是众所周知的事情,近几年的题目非常非常的多。

搜索的基本理论:

1、回溯法:当把问题分成若干个步骤并递归求解时,如果当前步骤没有合法选择,则函数将返回上一级递归调用,这种现象就称回溯。

2、路径寻找问题:路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条从初始状态到终止状态的最优路径,而不是像回溯法那样找到一个符合某些要求的解。

常见的两种方法是:深度优先搜索,广度优先搜索。

具体例题分析:

1、模型一:

2016第三题

凑算式
       B      DEF
A + — + -——— = 10
       C       GHI
(如果显示有问题,可以参见【图1.jpg】)
这个算式中A~I代表1~9的数字,不同的字母代表不同的数字。
比如:
6+8/3+952/714 就是一种解法,
5+3/1+972/486 是另一种解法。
这个算式一共有多少种解法?
注意:你提交应该是个整数,不要填写任何多余的内容或说明性文字。

#include<iostream>using namespace std;
int b[10];
int visited[10]={0};
void dfs(int k,int i);
void sovle();
int sum=0;
int main()
{int i;for(i=1;i<=9;i++){dfs(1,i);visited[i]=0;}printf("%d\n",sum);return 0;
} void dfs(int k,int i)
{int j;visited[i]=1;b[k]=i;if(k==9){sovle();}else{for(j=1;j<=9;j++){if(visited[j]==0){dfs(k+1,j);visited[j]=0;}}}
}
//先操作,再选择。
void sovle()
{int i;int x1,x2,x3;x1=b[2]*(b[7]*100+b[8]*10+b[9]);x2=b[3]*(b[4]*100+b[5]*10+b[6]);x3=(10-b[1])*(b[7]*100+b[8]*10+b[9])*b[3];if(x1+x2==x3){sum++;}
}

这道题目,我们看都不用看,果断选择回溯,因为,题意就是对9个数进行排列,然后,找到一个符合标准的排列时,加1.同时回溯法也是解决排列组合的一种很好的方法。但是这道题目麻烦在精度上面,我们必须要对分母进行通分。这个地方是出题人的一个变化的地方,因为以前考的都不用考虑精度,为啥呢?因为就比如2015年的三羊献瑞一样,它是乘法加法运算,算出的都是整数。

当然,我建议在考场直接用c++的next_permutation()这个函数,速度快。

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{int x1,x2,x3;int a[9];int i;int sum=0;for(i=0;i<9;i++){a[i]=i+1;}while(next_permutation(a,a+9)){x1=a[1]*(a[6]*100+a[7]*10+a[8]);x2=a[2]*(a[3]*100+a[4]*10+a[5]);x3=(10-a[0])*(a[2]*(a[6]*100+a[7]*10+a[8]));if(x1+x2==x3){sum++;}}printf("%d\n",sum);return 0;
}

模型二:

2016蓝桥杯第6题:方格填数;

方格填数

如下的10个格子

(如果显示有问题,也可以参看【图1.jpg】)

填入0~9的数字。要求:连续的两个数字不能相邻。
(左右、上下、对角都算相邻)

一共有多少种可能的填数方案?

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

          我的分析:这道题目,在回溯法应用于排列中算是一道比较有创意的题,首先,填数的过程就是一个排列,而排列往往用回溯,因为回溯法专门对那种解空间已知的,且解的成分独立,不相同。首先,我们要有方格存储,我们定义一个二维数组即可。在填数的过程中,应划分三块(按次数哈)。还有一点注意就是填数是有顺序的,就是第二个填入的数只需和第一个比较即可,不用和上下左右都比较。(我第一次做就犯了这个低级的错误)。
#include<iostream>using namespace std;
int graph[3][4]={0};
int visited[10]={0};  //候选集
int sum=0;
void dfs(int k,int i);
int main()
{int j;for(j=0;j<=9;j++){dfs(1,j);visited[j]=0;}printf("%d\n",sum);return 0;
} void dfs(int k,int i)
{int x1,x2;int j;
//  int j1,j2;visited[i]=1;//k决定了对哪个框进行操作。 //以下就是进行操作。 if(k>=8){x1=2;x2=k%8;graph[x1][x2]=i;//下面是检验; if(x2==0){if((graph[x1-1][x2]-graph[x1][x2]==1)||(graph[x1-1][x2]-graph[x1][x2]==-1)||(graph[x1][x2]-graph[x1-1][x2+1]==-1)||(graph[x1][x2]-graph[x1-1][x2+1]==1)){return;}}else{if(x2==1){if((graph[x1-1][x2]-graph[x1][x2]==1)||(graph[x1-1][x2]-graph[x1][x2]==-1)||(graph[x1][x2]-graph[x1][x2-1]==1)||(graph[x1][x2]-graph[x1][x2-1]==-1)||(graph[x1][x2]-graph[x1-1][x2-1]==1)||(graph[x1][x2]-graph[x1-1][x2-1]==-1)||(graph[x1][x2]-graph[x1-1][x2+1]==1)||(graph[x1][x2]-graph[x1-1][x2+1]==-1)){return;}}else{if((graph[x1-1][x2]-graph[x1][x2]==1)||(graph[x1-1][x2]-graph[x1][x2]==-1)||(graph[x1][x2]-graph[x1-1][x2-1]==1)||(graph[x1][x2]-graph[x1-1][x2-1]==-1)||(graph[x1][x2]-graph[x1][x2-1]==1)||(graph[x1][x2]-graph[x1][x2-1]==-1)||(graph[x1][x2]-graph[x1-1][x2+1]==1)||(graph[x1][x2]-graph[x1-1][x2+1]==-1)){return;}}} }else{if(k>=4){x1=1;x2=k%4;graph[x1][x2]=i;if(x2==0){if((graph[x1-1][x2+1]-graph[x1][x2]==1)||(graph[x1][x2]-graph[x1-1][x2+1]==1)){return;}}else{if(x2==1){if((graph[x1-1][x2]-graph[x1][x2]==1)||(graph[x1-1][x2]-graph[x1][x2]==-1)||(graph[x1][x2]-graph[x1][x2-1]==-1)||(graph[x1][x2]-graph[x1][x2-1]==1)||(graph[x1][x2]-graph[x1-1][x2+1]==-1)||(graph[x1][x2]-graph[x1-1][x2+1]==1)){return;}}else{if(x2==2){if((graph[x1][x2]-graph[x1][x2-1]==1)||(graph[x1][x2]-graph[x1][x2-1]==-1)||(graph[x1][x2]-graph[x1-1][x2-1]==1)||(graph[x1][x2]-graph[x1-1][x2-1]==-1)||(graph[x1][x2]-graph[x1-1][x2]==1)||(graph[x1][x2]-graph[x1-1][x2]==-1)||(graph[x1][x2]-graph[x1-1][x2+1]==1)||(graph[x1][x2]-graph[x1-1][x2+1]==-1)){return;}}else{if((graph[x1][x2]-graph[x1][x2-1]==1)||(graph[x1][x2]-graph[x1][x2-1]==-1)||(graph[x1][x2]-graph[x1-1][x2-1]==1)||(graph[x1][x2]-graph[x1-1][x2-1]==-1)||(graph[x1][x2]-graph[x1-1][x2]==1)||(graph[x1][x2]-graph[x1-1][x2]==-1)){return;}}}} }else{x1=0;x2=k%4;graph[x1][x2]=i;if(x2==2){if((graph[x1][x2]-graph[x1][x2-1]==1)||(graph[x1][x2]-graph[x1][x2-1]==-1)){return;}}else{if(x2==3){if((graph[x1][x2]-graph[x1][x2-1]==1)||(graph[x1][x2]-graph[x1][x2-1]==-1)){return;}}}}}if(k==10){sum=sum+1; return;}else{for(j=0;j<=9;j++){if(visited[j]==0){dfs(k+1,j);visited[j]=0;}}}
}
//先进行操作,然后,深搜,

此时对我的搜获其实挺大的,因为,以前回溯法解决排列时,大多是算式的题目,最后都回溯到相应k,然后进行一波操作。但是此题,我在做时并没这么做,visited[10]的工作当然一开始就弄了,但是在存数的过程中,存完后我也进行相应的比较了,即验证工作放到了每一步过程中。这种处理方法主要是受蓝桥杯上的lift and throw那道题的影响。of couse ,如果把验证放到最后,也是可以的,那这样的话,直接用c++的模板即可。

但是,并不是验证过程放到最后就万事大吉的,有些时候,该还的还得还。
模型三:
      题目:猜算式
你一定还记得小学学习过的乘法计算过程,比如:
   273
x   15
------
  1365
  273
------
  4095
  
请你观察如下的乘法算式
    ***
x   ***
--------
    ***
   ***
  ***
--------
  *****
星号代表某位数字,注意这些星号中,
0~9中的每个数字都恰好用了2次。
(如因字体而产生对齐问题,请参看图p1.jpg)
请写出这个式子最终计算的结果,就是那个5位数是多少?
注意:只需要填写一个整数,不要填写任何多余的内容。比如说明文字。
分析:   我拿到这道题的时候,第一感觉也是回溯法,回溯20个数,然后拿到后,再最后进行一波验证。包括,我那天晚上把这道题目拿给去年获得一等奖的室友看,他的想法也是如此,直接回溯,信心满满的。。。。。可是的话,这道题目用回溯解真的不合适,因为,它有20个位置变量需要填充。哪怕,你像我上一题一样中途验证也没用。出不来结果。其实解题,真的是一门学问,回溯法虽然可以解决这种解空间明确,且元素只用一次的题目,但一旦需要排列的数超过一定数就基本不得行了。     然后我们仔细的看题意,发现只要我们知道前六个,就可以依次算出后面的所有。然后在这我又犯了一个错误,直接暴力了六个数----2333333,直接枚举两个数可好。。。。。总而言之,此题值得我们对回溯法使用时要谨慎。并且以后遇到此类模型题,不要犹豫,就是简单枚举。

#include<iostream>
using namespace std;
int a[6];
int pd();
int main()
{int i,j;for(i=100;i<999;i++){for(j=100;j<999;j++){a[0]=i;a[1]=j;a[2]=i*(j%10);a[3]=i*(j/10%10);a[4]=i*(j/100%10);a[5]=i*j;if(a[2]<100||a[2]>999){continue;}if(a[3]<100||a[3]>999){continue;}if(a[4]<100||a[4]>999){continue;}if(a[5]<10000||a[5]>99999){continue;}if(pd()){printf("%d\n",a[5]);break;} }}return 0;
}
int pd()
{int t;int i;int x; int b[10]={0};for(i=0;i<6;i++){t=a[i];while(t>0){x=t%10;b[x]++;if(b[x]>2){return 0;}t=t/10;}  }return 1;
}

还有注意的一点,注意,对后面这几个进行一个位数的限制。

模型四:
     2016  第7题
第七题:

剪邮票

如【图1.jpg】, 有12张连在一起的12生肖的邮票。
现在你要从中剪下5张来,要求必须是连着的。
(仅仅连接一个角不算相连)
比如,【图2.jpg】,【图3.jpg】中,粉红色所示部分就是合格的剪取。

请你计算,一共有多少种不同的剪取方法。

请填写表示方案数目的整数。
注意:你提交的应该是一个整数,不要填写任何多余的内容或说明性文字。

分析:此题是非常值得学习的一道,显然它并不是数的排列,我们观察到的是数的组合,那怎么来思考呢?一般会想到两种方案:一种是原始的路径搜索问题,因为,在这其中就像迷宫一样,需要我们选一个起始点,然后依次深搜,到边界就返回。但是这种想法藐视不行,行了也很复杂。故我采用的是第二种,因为毕竟这张方格以数为主,则可以用组合。然后对这个组合进行验证判断(用深搜判断即可)。
#include<iostream>
#include<algorithm>
using namespace std;
int visited[13]={0};
int b[6]={0};//这样做适合排列,不适合组合
int huoxuan[13]={0};
int sum=0;
void dfs(int k,int i);
void dfs1(int i);
void sovle();
int main()
{dfs(0,0);printf("%d\n",sum);return 0;
}void dfs(int k,int i)
{int j;visited[i]=1;b[k]=i;if(k==5){sovle();return;}else{for(j=1;j<=12;j++){if(visited[j]==0&&j>b[k]){dfs(k+1,j);visited[j]=0;}}}
}
//组合再修改毋庸置疑.
//我下面这种解决方案是很值得思考的,即根本不符合题意。
//往大了取;
void sovle()
{int i,j;int x;int flag=0;for(i=1;i<13;i++){huoxuan[i]=visited[i];}for(i=1;i<13;i++){if(huoxuan[i]==1){break;}} //拿到最小的那个。 dfs1(i);for(i=1;i<13;i++){if(huoxuan[i]==1){break;}}if(i==13){
//      for(i=1;i<13;i++)
//      {
//          if(visited[i]==1)
//          {
//              printf("%d ",i);
//          }
//      }
//      printf("\n");sum++;}}void dfs1(int i)
{int x1,x2;if(i>=13){return;}huoxuan[i]=0;if(i-4>0){if(huoxuan[i-4]==1){dfs1(i-4);}}if((i-1)%4>0){if(huoxuan[i-1]==1){dfs1(i-1);}}if((i+1)%4!=1){if(huoxuan[i+1]==1){dfs1(i+1);}}if((i+4)<13){if(huoxuan[i+4]==1){dfs1(i+4);}}
}

总结,当然,在搜索这块地题目还有很多,比如八数码,倒水问题,但是,我觉得在解决题目的时候,思路要清晰,比如回溯法吧,它并不是是个搜索就能去解决的,并且其写法也多样,扩展验证,还是最后验证,这要看个人,它也常常使用在排列,已经解空间已知的状况。而路径搜索问题,则常常采用的是深搜和广搜,这有什么特点呢?一般来说解决有初始目标 有终极目标的问题,并且在这其中,每一步的获选集是不同的,可能一个可能两个。如果每次获选集一样这就是传说中的树的遍历了,题目也很多。

蓝桥杯及其搜索算法总结相关推荐

  1. 蓝桥杯Java——DFS深度优先搜索算法

    目录 基本概念 算法思想 模板 例子 基本概念 深度优先搜索算法(Depth First Search,简称DFS):一种用于遍历或搜索树或图的算法. 沿着树的深度遍历树的节点,尽可能深的搜索树的分支 ...

  2. 第十届蓝桥杯大赛软件类决赛 Java大学C组

    蓝桥杯2019国赛Java大学C组题 试题 A: 奇数倍数 试题 B: 递增序列 试题 C: 平方拆分 试题 D: 切割 试题 E: 序列求和 试题 F: 最长子序列 试题 G: 数正方形 试题 H: ...

  3. 蓝桥杯青少年创意编程C++组赛前集训教程包

    1 蓝桥杯青少年创意编程C++组 赛前集训教程包 版本-190919 蓝桥杯大赛组 2 目录 第01 课基本数据类型及运算符...................................... ...

  4. 蓝桥杯评分标准_第十届蓝桥杯软件个人赛校内选拔赛评分标准和选拔标准.doc...

    第十届"蓝桥杯"软件个人赛校内选拔赛评分标准和选拔标准 一.竞赛规则 1. 本次"蓝桥杯"校内选拔赛比赛平台: HYPERLINK "" . ...

  5. 蓝桥杯算法训练-24点(Python)

    问题描述 24点游戏是一个非常有意思的游戏,很流行,玩法很简单:给你4张牌,每张牌上有数字(其中A代表1,J代表11,Q代表12,K代表13),你可以利用数学中的加.减.乘.除以及括号想办法得到24, ...

  6. 2022年蓝桥杯Python程序设计B组思路和代码分享

    2022年蓝桥杯Python程序设计B组比赛结束了,分享一下题目以及思路. 文章目录 A:排列字母 题目: 思路: 代码: B: 寻找整数 题目: 思路: 代码: C: 纸张尺寸 题目: 思路: 代码 ...

  7. 第五届蓝桥杯真题解析【JavaC组】

    第五届蓝桥杯真题解析[JavaC组] 业精于勤,荒于嬉:行成于思,毁于随.--韩愈 文章目录 ***第五届蓝桥杯真题解析[JavaC组]*** 前言 A:猜年龄 B:等额本金 C:猜字母 D:大衍数列 ...

  8. 第十三届蓝桥杯省赛python(B组)赛后总结

    前言:这次蓝桥杯比赛,我获得了python组的二等奖(下图中最后一行是我,差几名拿省一).其实能获得这个成绩也算意料之外,情理之中吧.赛前也挺迷茫,自己到底能不能获奖,已经大三下了,还要准备考教资,找 ...

  9. 蓝桥杯书的笔记(二:接上篇蓝桥云课里的内容,C++)

    https://www.lanqiao.cn/courses/3993/learning/?id=248899 蓝桥云课的笔记 打表法和模拟法 算式问题 求值 既约分数 天干地支 总结 递推法与递归法 ...

最新文章

  1. FastAPI 之自动化测试数据库接口
  2. Go 语言编程 — 运算符
  3. python引入同目录文件_Python的文件目录操作
  4. TP查询数据库多维数组
  5. jq fileupload 设置最大文件大小5m_我猜你并不会设置“分辨率”
  6. java生成8位邀请码,邀请码生成器Java代码
  7. freopen()函数文件流重定向和文件流的清除
  8. 【转】javascript Object使用Array的方法
  9. VSLAM之边缘化 Marginalization 和 FEJ (First Estimated Jocobian)
  10. 百度——测试开发实习生面试记录
  11. 2021最后一个月了,你找到带回家的那个她了吗?送你999朵玫瑰。
  12. Axure视频教程2:制作第一个原型
  13. PyCharm下载安装
  14. Windows和Ubuntu系统文件无法粘贴问题
  15. 电磁场与仿真软件(28)
  16. 彻底干净地卸载 Visual Studio 系列
  17. FE内容付费系统源码
  18. 5h是什么意思_鱼竿5H,7H,8H都是什么意思
  19. JavaScript实现类似sleep()的多种方式
  20. 页面首次加载,脚本失效,打开F12后功能恢复正常

热门文章

  1. mybatis一对多的2种写法
  2. (Tekla Structures二次开发)使用VS创建Tekla Structures插件的模板
  3. 小武学fpgaStep1
  4. 阿里云的核心技术要点
  5. linux pv 文件夹,Linux 实用命令 - pv
  6. MT6753和MT6737 4G和以太网同时使用问题,测试记录
  7. python自动排版公众号_自制微信公众号一键排版工具
  8. 调皮的表情图(Emoji)
  9. 破解花式反爬之大众点评-下
  10. Python 用turtle画多个八边形组成的蜘蛛网