嗯哼!数月未出现的学生党蒟蒻,出关了。虽说放暑假已经有一些时日了,呃呃呃,但没关系,家人们别介意,最近在洛谷做了一些题,找到了一些比较适合像本蒟蒻一样的新手刷一下的广搜,也就是BFS。好,话不多说,上强度。
1.P1683 入门
先放个题目,方便家人们阅读,嘻嘻嘻。
首先读题,很容易发现,这就是一道赤裸裸的广搜。
接着看样例和数据范围(必须看,尤为重要)
一看这输入样例,搜索落实了。而且有实力的家人们一定发现了,这就是妥妥的连通性问题,其实是比较水的,至于这个文章的描述,呃呃呃,人家语文水平好,甘拜下风。
分析:
其次,和平时的广度优先搜索的套路一样,先开一个char类型的mp[23][23]的数组,代表地图,其次用vis[23][23]表示该点是否搜索过,再定义dx[],dy[],表示上下左右的点,该题本蒟蒻用的是上右下左,在代码中也注释了,再用STL的queue的队列逐个搜索,直到得到答案。要注意的是,这道题中的队列是一直搜索到没有路为止的。
或许会有家人们质疑,真的这么简单?实不相瞒,这只是一道很普通的普及-
好,由于这题比较简单,本蒟蒻就直接上代码了,希望家人们遵循洛谷的规则,阿里嘎多。
代码如下:
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
char mp[23][23];
bool vis[23][23];
int dx[4]={-1,0,1,0}; //上右下左
int dy[4]={0,1,0,-1}; //上右下左
int w,h,x,y,ans=1;
struct node{
int x,y;
};
bool check(int x,int y){
if((mp[x-1][y]=='#'||vis[x-1][y])&&
(mp[x][y-1]=='#'||vis[x][y-1])&&
(mp[x+1][y]=='#'||vis[x+1][y])&&
(mp[x][y+1]=='#'||vis[x][y+1]))
return true;
else return false;
}
void bfs(int x,int y){
queue<node> q;
node Front;
Front.x=x;Front.y=y;
q.push(Front);
while(!q.empty()){
node fron=q.front();
q.pop();
if(check(fron.x,fron.y)){
continue;
}
for(int i=0;i<4;i++){
node now;
now.x=fron.x+dx[i];
now.y=fron.y+dy[i];
if(mp[now.x][now.y]=='#'||vis[now.x][now.y]) continue;
q.push(now);
vis[now.x][now.y]=true;
ans++;
}
}
}
int main(){
for(int i=0;i<23;i++){
for(int j=0;j<23;j++){
vis[i][j]=true;
}
}
cin>>w>>h;
for(int i=1;i<=h;i++){
for(int j=1;j<=w;j++){
cin>>mp[i][j];
vis[i][j]=false;
if(mp[i][j]=='@'){
x=i;
y=j;
}
}
}
vis[x][y]=true;
bfs(x,y);
cout<<ans;
return 0;
}
接着就可以直接AC了。好,趁热打铁,接着下一道。
2.P1747 好奇怪的游戏
照常,上题目:
这是一道普及/提高-,但其实本蒟蒻觉得难度还是一样,看来下一篇还得上点强度才行,嘻嘻嘻。
读题,这这这,居然有马走日也能走田的游戏!?难评,逆天。
接下来是输入输出样例和数据范围:
分析:
两匹马,黑马,白马。呃呃呃,家人们,管他黑马白马,能解出题的就是好代码!!!
其实,基本思路都是差不多的,我们只需要将dx[],dy[]数组的数据改一改,也就是下一步的数据改一下,有点繁琐,但管他呢,还是那句“能解出题的就是好代码”(狗头)(狗头)。
每一步一共可以扩展12个点,如下:
dx[12]={-2,-1,1,2,2,1,-1,-2,-2,2,2,-2};
dy[12]={-1,-2,-2,-1,1,2,2,1,-2,-2,2,2};
不一定要按照我的顺序,但一定要相匹配,不然就WA了。
另外,定义的结构体node中,要加上个step,记录下白马或黑马从(1,1)到该节点的步数。每拓展一个节点就+1,注意不是+7。
而两匹马要分别广搜,不用担心时间复杂度,因为根本剪不了枝,至少本蒟蒻不行。或许有家人觉得距离目标节点越来越远的节点不用搜索,但实则不然,因为会有一些特殊情况,必须先走离目标节点较远的田,再走日才能到达。
但家人们不用担心,时间复杂度完全够用,因为x,y都小于20。
好,上代码:
#include<iostream>
#include<queue>
using namespace std;
int x1,y1,x2,y2;
int dx[12]={-2,-1,1,2,2,1,-1,-2,-2,2,2,-2};
int dy[12]={-1,-2,-2,-1,1,2,2,1,-2,-2,2,2};
bool vis[1010][1010];
struct node{
int x,y,step=0;
};
int bfs(int x,int y){
for(int i=0;i<1010;i++){
for(int j=0;j<1010;j++){
vis[i][j]=false;
}
}
queue<node> q;
node fron;
fron.x=x;fron.y=y;
q.push(fron);
while(!q.empty()){
fron=q.front();
q.pop();
for(int i=0;i<12;i++){
node now;
now.x=fron.x+dx[i];
now.y=fron.y+dy[i];
if(vis[now.x][now.y]||now.x<1||now.y<1)continue;
now.step=fron.step+1;
q.push(now);
vis[now.x][now.y]=true;
if(now.x==1&&now.y==1){
return now.step;
}
// cout<<now.x<<" "<<now.y<<" "<<now.step<<endl;
}
// cout<<endl;
}
}
int main(){
cin>>x1>>y1>>x2>>y2;
cout<<bfs(x1,y1)<<endl<<bfs(x2,y2);
return 0;
}
细节的家人们会发现有两行注释了,那是本蒟蒻当时调试时写的,自己动手写的家人们也可以参考一下我是怎么调试的。
以上是洛谷中的两道关于BFS的题目,贪多嚼不烂,今天就先讲着两题,这两题比较适合练速度,加深理解的,初学者也可以先从这两题开始入手,一开始可能会写个把来小时,但这是正常现象,这种还是得多练的,但毕竟也不太难。
本蒟蒻要下了,家人们,如果有问题可以随时提出,谢谢家人们的鼓励与支持。
(侵删)