BFS思想:
从初始结点开始,应用算符生成第一层结点,检查目标结点是否在这些后继结点中,若没有,再用产生式规则将所有第一层的结点逐一扩展,得到第二层结点,并逐一检查第二层结点中是否包含目标结点。若没有,再用算符逐一扩展第二层所有结点……,如此依次扩展,直到发现目标结点为止 。
BFS就是对一个点的所有可以走的情况同时访问,一个层次一个层次地访问,所以称为宽度优先搜索(Breadth First Search)
而DFS是对一个点的可以走的一种情况进行访问,如果这种情况的下一个点还能走的话,在对这个点进行下一次的访问,这个是一个分支一个分支地访问,所以称为深度优先搜索(Depth First Search );
现在用图来讲一下哈:比如对于这个图来说:
BFS:如果A是起点的话,那么访问顺序是: A =》 B ,C =》D, E, F,而模拟这个过程的就是queue队列了,先把这一层的元素保存在队列之中,然后再逐个对队列里的元素进行操作。
DFS:如果derict数组的方向是左边的话,那么访问顺序是A =》B = 》D =》 E =》 C =》F,就是想把一个分支全部访问完了,在访问下一个分支。
这个题是经典的BFS,当初一直不想去整这种东西,这个题的话就是在访问的时候用pre记录一下该节点的上一个点,然后输出的时候利用一下stack栈的FILO就行了。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
const int N = 5;
const int maxn = 100000+10;
int derict[4][2] =
{
0,1,
0,-1,
1,0,
-1,0,
};
int maze[10][10];
struct Node
{
int x;
int y;
int pre;
}nod[maxn];//节点的坐标是x *N +y
bool vis[N][N];
void print()
{
int point = 4 *5 +4;
stack<Node>s;
for(int i=point ; ; i= nod[i].pre)
{
s.push(nod[i]);
// cout<<"("<<nod[i].x<<", "<<nod[i].y<<")"<<endl;
if(i==0)
break;
}
while(! s.empty())
{
cout<<"("<<s.top().x<<", "<<s.top().y<<")"<<endl;
s.pop();
}
}
void bfs(int x,int y)
{
int point = x *N +y;
nod[point].x = x;
nod[point].y = y;
nod[point].pre = -1;
vis[x][y] = true;
queue<Node>q;
q.push(nod[point]);
while(! q.empty())
{
Node temp = q.front();
q.pop();
for(int i=0 ;i < 4;i++)
{
int xx= temp.x +derict[i][0];
int yy= temp.y +derict[i][1];
if(xx>=0 && xx<N && yy>=0 &&yy <N && !vis[xx][yy] && maze[xx][yy]== 0)
{
vis[xx][yy] = true;
point= xx*5 + yy;
nod[point].x = xx;
nod[point].y = yy;
nod[point].pre = temp.x * 5 + temp.y;
q.push(nod[point]);
if(xx== 4 && yy== 4)
{
print();
return ;
}
}
}
}
}
int main()
{
memset(vis,false,sizeof(vis));
for(int i=0;i <N;i++)
{
for(int j=0;j<N ;j++)
{
scanf("%d",&maze[i][j]);
}
}
bfs(0,0);
return 0;
}
这个题的意思就是从start这层坐电梯到destination这一层,不过电梯在每层的有一个k[i],代表在这层只能上升或者下降k[i]层,所以用一个time数组记录一下按按钮的次数,直接把所有的情况走一遍就好了,到达了这层的话就输出,之后直接输出time[destination],就是按了多少次。当初错了一发,所以就用pre数组记录了一下,输出了一下,发现没有错误,后面才发现没有判断能不能到达的情况,所以》》》》
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
const int N = 5;
const int maxn = 100000+10;
int k[maxn];
int n,start,destination;
int ans;
bool vis[maxn];
int time[maxn];
int pre[maxn];
void BFS()
{
queue<int >q;
time[start] = 0;
q.push(start);
pre[start] = -1;
vis[start]= true;
while(! q.empty())
{
int temp = q.front();
q.pop();
int xx = temp + k[temp];
int yy = temp - k[temp];
if(xx>= 1 && xx <= n && !vis[xx])
{
pre[xx] = temp;
time[xx] = time[temp] +1;
if(xx == destination )
return ;
vis[xx] = true;
q.push(xx);
}
if(yy >= 1 && yy <= n && !vis[yy])
{
pre[yy] =temp;
vis[yy ] = true;
time[yy] = time[temp] +1;
if(yy == destination )
return ;
q.push(yy);
}
}
return ;
}
int main()
{
while(~scanf("%d",&n) && n)
{
memset(vis,false,sizeof(vis));
memset(time,0,sizeof(time));
scanf("%d%d",&start,&destination);
for(int i= 1;i <= n;i++)
scanf("%d",&k[i]);
BFS();
// for(int i=destination ; i!= - 1;i = pre[i])
// {
// cout<<i<<" ";
// }
// cout<<endl;
// for(int i= 1;i <=n ;i++)
// cout<<time[i]<<" ";
// cout<<endl;
if(start != destination && time[destination] ==0)//判断是否能够到达。
{
cout<<"-1"<<endl;
continue;
}
cout<<time[destination]<<endl;
}
return 0;
}
不知道为什么同样的代码在hdu上能过,在poj上却runtime error,我觉得肯定是我的代码有点问题吧,不然怎么会在poj上过不了呢,不过找了半天没找到。但我又想了一下,同样的题hdu能过,是不是hdu和poj的数据不一样呢?
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
const int N = 5;
const int maxn = 100000+10;
int start,destination;
int time[maxn];
bool vis[maxn];
void BFS()
{
queue<int >q;
time[start] =0;
q.push(start);
vis[start] = true;
while(! q.empty())
{
int temp=q.front();
q.pop();
int x = temp +1,y =temp-1,z=temp*2;
if(! vis[x] && x>=0 && x< maxn)
{
q.push(x);
time[x] =time[temp] +1;
if(x == destination)
return ;
vis[x] = true;
}
if(! vis[y] && y>=0 && y<maxn)
{
q.push(y);
time[y] =time[temp] +1;
if(y == destination)
return ;
vis[y] = true;
}
if(! vis[z] && z>=0 && z<maxn)
{
q.push(z);
time[z] =time[temp] +1;
if(x == destination)
return ;
vis[z] = true;
}
}
}
int main()
{
int n,m;
while(~scanf("%d%d",&start,&destination))
{
memset(vis,false,sizeof(vis));
memset(time,0,sizeof(time));
BFS();
cout<<time[destination]<<endl;
}
return 0;
}
#include <iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=40;
char ss[maxn][maxn][maxn];
bool vis[maxn][maxn][maxn];
struct Node
{
int c,x,y;
}s,e;//s代表start起点,e代表end终点,c,x,y分别代表层和坐标
int times[maxn][maxn][maxn];
int derict[6][3]=
{
-1,0,0,
1,0,0,
0,1,0,
0,-1,0,
0,0,-1,
0,0,1,
};//6个方向
int c,n,m;
void bfs()
{
vis[s.c][s.x][s.y] = true;
times[s.c][s.x][s.y] = 0;
queue<Node>q;
q.push(s);
while( ! q.empty())
{
Node t=q.front();
// cout<<t.c<<" "<<t.x<<" "<<t.y<<endl;
q.pop();
for(int i=0;i<6;i++)
{
int xx = t.c+derict[i][0];
int yy = t.x +derict[i][1];
int zz = t.y +derict[i][2];
if(xx >=0 && xx<c && yy>=0 && yy<n && zz>=0 && zz<m && !vis[xx][yy][zz] && (ss[xx][yy][zz] =='.' || ss[xx][yy][zz]== 'E') )
{
Node temp;
temp.c= xx;
temp.x=yy;
temp.y=zz;
times[xx][yy][zz] = times[t.c][t.x][t.y] +1;
if(xx == e.c && yy == e.x && zz == e.y)
return ;
vis[xx][yy][zz] = true;
q.push(temp);
}
}
}
}
int main()
{
while(~scanf("%d%d%d",&c,&n,&m) && (n || m|| c))
{
memset(times,0,sizeof(times));
memset(vis,false,sizeof(vis));
for(int i=0;i<c;i++)
{
for(int j=0;j<n;j++)
{
scanf("%s",ss[i][j]);
for(int x=0;x<m;x++)
{
if(ss[i][j][x] == 'S')
{
s.c=i;
s.x=j;
s.y=x;
}
if(ss[i][j][x] =='E')
{
e.c=i;;
e.x=j;
e.y=x;
}
}
}
}
// cout<<s.c<<" "<<s.x<<" "<<s.y<<endl;
// cout<<e.c<<" "<<e.x<<" "<<e.y<<endl;
bfs();
// for(int i=0;i<c;i++)
// {
// for(int j=0;j<n ;j++)
// {
// for(int x=0;x<m;x++)
// {
// cout<<times[i][j][x]<<" ";
// }
// cout<<endl;
// }
// cout<<endl;
// }
if(!(s.c==e.c && s.x==e.x && s.y==s.y))
{
if(!times[e.c][e.x][e.y])//判断是不是没有找到情况,这种的情况出现的条件是times[终点]==0 &&终点不等于起点
{
cout<<"Trapped!"<<endl;
}
else cout<<"Escaped in "<<times[e.c][e.x][e.y]<<" minute(s)."<<endl;
}
else cout<<0<<endl;
}
return 0;
}
这个题开始不知道怎么也过不了,后面重写一遍就过了,。。,
BFS的思路,然后就是每个人到每个@的时间用数组记录下来,然后之后进行比较;
#include<iostream>
#include<cstring>
#include<queue>
#include<string>
#include<cstdio>
using namespace std;
const int maxn=1000;
char s[maxn][maxn];
bool vis[maxn][maxn];
int time1[maxn][maxn];
int time2[maxn][maxn];
int n,m;
int derict[4][2]=
{
-1,0,
1,0,
0,-1,
0,1,
};
struct Node
{
int x;
int y;
}M,Y;
void BFS1()
{
vis[Y.x][Y.y] = true;
queue<Node>q;
q.push(Y);
time1[Y.x][Y.y] = 0;
while(! q.empty())
{
Node t= q.front();
q.pop();
for(int i=0;i<4;i++)
{
int xx = t.x + derict[i][0];
int yy = t.y + derict[i][1];
if(xx>=0 && xx<=n && yy>=0 && yy<m && !vis[xx][yy] && s[xx][yy]!='#')
{
Node temp;
temp.x = xx;
temp.y = yy;
time1[xx][yy] = time1[t.x][t.y] + 1;
vis[xx][yy] = true;
q.push(temp);
}
}
}
return ;
}
void BFS2()
{
vis[M.x][M.y] = true;
queue<Node>q;
q.push(M);
time2[M.x][M.y] = 0;
while(! q.empty())
{
Node t= q.front();
q.pop();
for(int i=0;i<4;i++)
{
int xx = t.x + derict[i][0];
int yy = t.y + derict[i][1];
if(xx>=0 && xx<=n && yy>=0 && yy<m && !vis[xx][yy] && s[xx][yy]!='#')
{
Node temp;
temp.x = xx;
temp.y = yy;
time2[xx][yy] = time2[t.x][t.y] + 1;
vis[xx][yy] = true;
q.push(temp);
}
}
}
return ;
}
int main()
{
while(~ scanf("%d%d",&n,&m))
{
memset(vis,false,sizeof(vis));
memset(time1,0,sizeof(time1));
memset(time2,0,sizeof(time2));
for(int i=0;i<n;i++)
{
scanf("%s",s[i]);
for(int j=0;j<m;j++)
{
if(s[i][j] == 'Y')
{
Y.x =i;
Y.y =j;
}
if(s[i][j] == 'M')
{
M.x = i;
M.y = j;
}
}
}
BFS1();
memset(vis,false,sizeof(vis));
BFS2();
long long ans=100000000;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(s[i][j] == '@')
{
if(time1[i][j] + time2[i][j] <ans)
{
ans=time1[i][j] + time2[i][j];
}
}
}
}
cout<<ans*11<<endl;
}
return 0;
}
题意:
从左上角到右下角的最短的时间;用一个times数组记录一下就行了。
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
const int maxn= 10000+10;
int n,m;
char s[maxn][maxn];
bool vis[maxn][maxn];
int times[maxn][maxn];
int derict[4][2]=
{
-1,0,
1,0,
0,-1,
0,1,
};
struct Node
{
int x;
int y;
};
void BFS()
{
vis[0][0] = true;
queue<Node>q;
Node tt ;
tt.x = 0;
tt.y = 0;
q.push(tt);
times[0][0] = 0;
while(! q.empty())
{
Node t;
t = q.front();
q.pop();
for(int i=0;i<4;i++)
{
int xx = t.x + derict[i][0];
int yy = t.y + derict[i][1];
if(xx>=0 && xx<n && yy>=0 && yy<m && !vis[xx][yy] && s[xx][yy] == '.')
{
Node temp;
temp.x =xx;
temp.y =yy;
q.push(temp);
times[xx][yy] = times[t.x][t.y] + 1;
vis[xx][yy] = true;
if(xx == n-1 && yy == m-1)
{
return ;
}
}
}
}
}
int main()
{
while(~ scanf("%d%d",&n,&m))
{
memset(vis,false,sizeof(vis));
memset(times,0,sizeof(times));
for(int i=0;i<n;i++)
{
scanf("%s",s[i]);
}
BFS();
cout<<times[n-1][m-1]+1<<endl;
}
return 0;
}
题意就是一个象棋中的马从一个点跳到另一个点最少要多少时间?
与普通的BFS不同的是:马的走法有8个日的方向;
#include<bits/stdc++.h>
using namespace std;
int a,b,c,d;
int derict[8][2]=
{
1,2,
2,1,
2,-1,
1,-2,
-1,-2,
-2,-1,
-2,1,
-1,2,
};
bool vis[100][100];
int times[100][100];
struct Node
{
int x,y;
};
void BFS()
{
Node tt;
tt.x =a;
tt.y =b;
queue<Node>q;
vis[a][b] = true;
times[a][b] = 0;
q.push(tt);
while(! q.empty())
{
Node t;
t=q.front();
q.pop();
for(int i=0;i<8;i++)
{
int xx= t.x+derict[i][0];
int yy =t.y+derict[i][1];
if(xx >=0 &&xx<=9 && yy>=0 && yy<=8 && !vis[xx][yy] )
{
Node temp;
temp.x = xx;
temp.y = yy;
vis[xx][yy] = true;
times[xx][yy] = times[t.x][t.y] + 1;
q.push(temp);
if(xx == c && yy == d)
return ;
}
}
}
}
int main()
{
while(~ scanf("%d%d%d%d",&a,&b,&c,&d))
{
memset(vis,false,sizeof(vis));
memset(times,0,sizeof(times));
BFS();
cout<<times[c][d];
}
return 0;
}