队列&广搜
搜索里有深搜,又有广搜,而广搜的基础就是队列。
队列是一种特殊的线性表,只能在一段插入,另一端输出。输出的那一端叫做队头,输入的那一端叫队尾。是一种先进先出(FIFO)的数据结构。
正经的队列:
头文件:#include <queue>
入队:q.push(要入队的数)
返回第一个元素:q.front( )
从队列中移除第一个元素:q.pop( )
查看队列中元素的个数:q.size( )
返回队列的最后一个元素:q.back( )
用数组模拟的队列:
可以定义数组q[100001](可大可小)
队头为head,队尾为tail
注意:
如图,head指向第一个实际元素的前一个位置,tail指向最后一个实际元素的位置
无论数组多大,总会有个界限,入队过多会溢出,而前面出队时会有空出来的位置,所以我们可以把一个数组循环使用。
代码如下:
void rudui(int x)
{tail++:
if(tail==n+)
tail=;
if(tail==head)//入队要判满
{printf("操作无效,队列已满");
return;}
q[tail]=x;
}
说了些基本定义,再来说说应用。
队列的应用和广搜是分不开的。
那什么是广搜?
就是一层一层的搜索,从第0层开始,每层都枚举出可能的情况,直到找到符合要求的情况为止
如图:
放个模板
这里是用数组模拟队列
int bfs()
{ 队列初始化;
head=;tail=;//记住tail指向最后一个实际元素!!
do{
head++;//head指向带扩展节点
for(int i=;i<=max;i++)//节点如何扩展
{
if(子节点符合条件)
{tail++;该节点入队;
if(与原来有重复)
{ 删除该节点;tail--;
}
else
{if(找到目标)输出并退出;
}
}
}
}while(head<tail);//队列不空就继续搜索
}
举个栗子:
例题1:
这个题就是广搜的典型例题。
在这道题中,所有非0数都可以看做是1,因为它们的值不影响判断。这样就可以用一个bool数组a[1001][1001]来表示这个矩阵
通过样例可以知道,矩阵的输入是没有空格的,所以要用字符型输入(这是个坑)
既然我们决定用bool型数组(只有0,1),而且还有前面那个坑。为了防止毒瘤的非法读入,我们先将整个a数组置为1。我们输入时判断一下,如果输入的字符是0,就把对应位置置为0。
然后就是搜索了。
先在main里找到1,再进行搜索,会省时间。
搜索时,记录下当前的i,j。从i,j的上下左右搜索,如果是1,就将这个位置的坐标放入队中,并将这个位置置为0,防止重复
入队的同时将队头出队,一直到队空为止,完成一次搜索,计数器加1.
代码如下:
#include<iostream>
#include<cstdio>
using namespace std;
int n,m,num,dx[]={-,,,},dy[]={,,,-};//预处理出4个方向
bool a[][];
void justdoit(int p,int q)
{ a[p][q]=;
int x,y,head,tail,i;
int h[][];
num++;
h[][]=p;h[][]=q;//h[head][1]为横坐标,h[head][2]为纵坐标
head=;tail=;
do{
head++;
for(int i=;i<=;i++)
{x=h[head][]+dx[i];y=h[head][]+dy[i];
if((a[x][y])&&(x>=)&&(y>=)&&(x<m)&&(y<n))
{tail++;
h[tail][]=x;//坐标入队
h[tail][]=y;
a[x][y]=;
}
}
}while(head<tail);
}//其实就是套模板
int main()
{char c[];
scanf("%d %d",&m,&n);
for(int i=;i<=m-;i++)
{for(int j=;j<=n-;j++)
a[i][j]=;
}
for(int i=;i<m;i++)
{
scanf("%s",c);
for(int j=;j<n;j++)
{if(c[j]==''){a[i][j]=;
}
}
}
for(int i=;i<m;i++)
{for(int j=;j<n;j++)
if(a[i][j])justdoit(i,j);
}
printf("%d",num);
}
例题2:
这个题显然没有什么数学规律可以解方程什么的,所以我们好像只能搜索了。
从a,b两点搜索到1会造成一些时间的浪费,因为(1,1)在棋盘的一角,而a和b在棋盘中间,会造成在左下角方向的浪费
如图:
如果从a搜索到(1,1),会造成在箭头方向上的浪费,所以我们从(1,1)开始搜,搜到a停止
这里有两个点,参照对a的搜索方式,我们可以a,b一起搜。
先用p[101][101]数组将棋盘表示出来,所有的p[i][j]都初始化为-1,表示都没有到过
同时用dl[100001][4]数组来模仿队列,记录当前的所有到过点的坐标
其中dl[i][1]为横坐标,dl[i][2]为纵坐标,dl[i][3]为到达当前坐标所用最小步数
边界:点的横纵坐标大于0
一旦到达a和b,输出并结束程序
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int ax,ay,bx,by,dx[]={-,-,-,-,,,,,-,-,,},dy[]={-,,-,,-,,-,,-,,-,};
int numa,numb;
int main()
{
scanf("%d%d%d%d",&ax,&ay,&bx,&by);
int dl[][]={};
int p[][];
dl[][]=;dl[][]=;dl[][]=;//这里从(1,1)开始跳,跳到a,b两点坐标结束(???)
memset(p,0xff,sizeof(p));//dl[i][3]记录跳到(dl[i][1],dl[i][2]的步数)
p[][]=;//用p数组表示棋盘上的每个点,到过就+1,初始为-1(方便统计只到过一次的点)
int head=,tail=;
while(head<=tail)
{
for(int i=;i<=;i++)
{int x=dl[head][]+dx[i],y=dl[head][]+dy[i];//12个方向
if(x>&&y>)//若从(1,1)开始跳,则不能超出棋盘
{
if(p[x][y]==-)//之前没有到过这个点
{p[x][y]=dl[head][]+;//到达点(x,y)所需要的步数p为跳到上一个(x,y)的步数再加一
tail++;
getchar();
dl[tail][]=x;//记录坐标
dl[tail][]=y;
dl[tail][]=p[x][y];//记录跳到(x,y)的步数
}
if(p[ax][ay]>&&p[bx][by]>)//肯定不可能0步就跳到
{printf("%d\n%d\n",p[ax][ay],p[bx][by]);
return ;
}
}
} head++;
}
}
队列&广搜的更多相关文章
- HDU-1226-超级密码-队列+广搜+大数取模
Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 密码是一个C进制的数,并且只能由给定的M个数字构成,同 ...
- SPOJ-Grid ,水广搜easy bfs
SERGRID - Grid 一个水广搜我竟然纠结了这么久,三天不练手生啊,况且我快三个月没练过搜索了... 题意:n*m的方格,每个格子有一个数,意味着在此方格上你可以上下左右移动s[x][y]个格 ...
- hdu 1253 胜利大逃亡(广搜,队列,三维,简单)
题目 原来光搜是用队列的,深搜才用栈,我好白痴啊,居然搞错了 三维的基础的广搜题 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #in ...
- VIJOS-P1340 拯救ice-cream(广搜+优先级队列)
题意:从s到m的最短时间.(“o"不能走,‘#’走一个花两个单位时间,‘.'走一个花一个单位时间) 思路:广搜和优先队列. #include <stdio.h> #include ...
- poj 3278:Catch That Cow(简单一维广搜)
Catch That Cow Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 45648 Accepted: 14310 ...
- 双向广搜 POJ 3126 Prime Path
POJ 3126 Prime Path Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16204 Accepted ...
- hdu 1242:Rescue(BFS广搜 + 优先队列)
Rescue Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submis ...
- HDU 1253 (简单三维广搜) 胜利大逃亡
奇葩!这么简单的广搜居然爆内存了,而且一直爆,一直爆,Orz 而且我也优化过了的啊,尼玛还是一直爆! 先把代码贴上睡觉去了,明天再来弄 //#define LOCAL #include <ios ...
- hdu 1175 连连看 (广搜,注意解题思维,简单)
题目 解析见代码 #define _CRT_SECURE_NO_WARNINGS //这是非一般的最短路,所以广搜到的最短的路不一定是所要的路线 //所以应该把所有的路径都搜索出来,找到最短的转折数, ...
随机推荐
- 『TensorFlow』网络操作API_中_损失函数及分类器
一.误差值 度量两个张量或者一个张量和零之间的损失误差,这个可用于在一个回归任务或者用于正则的目的(权重衰减). l2_loss tf.nn.l2_loss(t, name=None) 解释:这个函数 ...
- openLDAP安装时无法操作根节点数据,提示的是This base cannot be created with PLA.
1.无法操作根节点数据,提示的是This base cannot be created with PLA. 解决办法 1)添加一个base.ldif文件,里面的dc和配置文件里的保持一致即可 dn: ...
- 数据结构与算法之PHP排序算法(堆排序)
一.堆的定义 堆通常是一个可以被看做一棵树的数组对象,其任一非叶节点满足以下性质: 1)堆中某个节点的值总是不大于或不小于其父节点的值: 每个节点的值都大于或等于其左右子节点的值,称为大顶堆.即:ar ...
- ansible的管理与剧本
首先我们安装一个ansible. 在7版本,直接用yum安装就可以 yum -y install ansible 然后清空ansible的配置文件,在里面写入自己需要管理的服务器的ip和相应的登陆密码 ...
- 企业面试题:Buffer与cache的区别?
buffer缓冲 cache是缓存. 写缓冲,读缓存.简单点说,buffer是即将要被写入磁盘的,而cache是被从磁盘中读出来的.缓冲(buffers)是根据磁盘的读写设计的,把分散的写操作集中进行 ...
- GDT全局描述符表
GDT全局描述符表 什么是GDT全局描述符表 GDT全称为Global Descriptor Table,全局描述符表. 保护模式的寻址方式不在使用寄存器分段的方式直接寻址方式了.而采用的是使用GDT ...
- linux远程管理常用命令
目标 关机/重启 shutdown 查看或配置网卡信息 ifconfig ping 远程登录和复制文件 ssh scp 01. 关机/重启 序号 命令 对应英文 作用 01 shutdown 选项 时 ...
- python与sqlserver接口包pymssql
包下载地址(对应着自己的电脑和Python的版本下载即可,我电脑是win32,Python是3.6的) https://pypi.python.org/pypi/pymssql/ 下载后我放到了d盘中 ...
- ant通配符
ANT通配符有三种: 通配符 说明 ? 匹配任何单字符 * 匹配0或者任意数量的字符 ** 匹配0或者更多的目录 例子: URL路径 说明 /app/*.x 匹配(Matches)所有在app路径下的 ...
- 自动化测试-12.selenium的弹出框处理
前言 不是所有的弹出框都叫alert,在使用alert方法前,先要识别出到底是不是alert.先认清楚alert长什么样子,下次碰到了,就可以用对应方法解决. alert\confirm\prompt ...