基础搜索入门BFS

BFS全称宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。通俗一点的说就像你向一块平静的湖面丢一块石头,会荡出一层一层的水波,而且水波是由近及远的,通常BFS搜索需要搭配队列或者优先队列来辅助搜索过程。

HDU1253
广度优先搜索第一道题 bfs + queue

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <queue>
using namespace std;
struct Node{int x,y,z,step;
};
queue<Node>q;
int map[50][50][50];
int visited[50][50][50];
int dx[6] = { 1,0,-1,0,0,0 };
int dy[6] = { 0,1,0,-1,0,0 };
int dz[6] = { 0,0,0,0,1,-1 };
int BFS(int a,int b,int c,int time)
{while(q.empty()==false){Node p = q.front();q.pop();if(time<p.step){break;}for(int i = 0;i < 6;i++){int nx = p.x+dx[i];int ny = p.y+dy[i];int nz = p.z+dz[i];if(nx<0||nx>=a||ny<0||ny>=b||nz<0||nz>=c||visited[nx][ny][nz]==1||map[nx][ny][nz]==1){continue;}Node ptr;ptr.x = nx;ptr.y = ny;ptr.z = nz;ptr.step = p.step+1;q.push(ptr);visited[ptr.x][ptr.y][ptr.z] = 1;if(nx == a-1 && ny == b-1 && nz == c-1){return ptr.step;}}}return 2000;
}
int main()
{int a,b,c,t,time;scanf("%d",&t);while(t--){scanf("%d%d%d%d",&a,&b,&c,&time);for (int i = 0; i < a; i++){for (int j = 0; j < b; j++){for(int k = 0;k < c;k++){scanf("%d",&map[i][j][k]);visited[i][j][k] = 0;}}}while(!q.empty()){q.pop();}Node start;start.x = 0;start.y = 0;start.z = 0;start.step = 0;q.push(start);visited[0][0][0] = 1;int ans = BFS(a,b,c,time);if(ans>time){printf("-1\n");}else{printf("%d\n",ans);}}return 0;
}

HDU1242
搜索第二题,bfs + queue,但是经过后来的学习发现这道题这么做是错误的,应该用优先队列.
目标只有一个,但是救援人员可以有多个,测试数据有点水没出到位详情请右转正解链接

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int m,n,start_x,start_y;
struct Node{int x,y,step;bool operator <(const Node &s)const{return s.step < step;}
};
char map[201][201];
int visited[201][201];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};
priority_queue<Node>q;
int BFS()
{while(!q.empty()){Node p = q.top();q.pop();for(int i = 0;i < 4;i++){int nx = p.x+dx[i];int ny = p.y+dy[i];int step = p.step+1;if(nx<0||nx>=m||ny<0||ny>=n||map[nx][ny]=='#'||visited[nx][ny]==1){continue;}Node ptr;ptr.x = nx;ptr.y = ny;ptr.step = step;if(map[ptr.x][ptr.y]=='x'){//    cout<<"jinlai"<<endl;ptr.step += 1; }if(map[nx][ny]=='r'){return ptr.step;}q.push(ptr);visited[ptr.x][ptr.y] = 1;}}return -1;
}
int main()
{while(cin>>m>>n){for(int i = 0;i < m;i++){for(int j = 0;j < n;j++){cin>>map[i][j];visited[i][j] = 0;if(map[i][j] == 'a'){start_x = i,start_y = j;}}}while(!q.empty()){q.pop();}Node start;start.x = start_x;start.y = start_y;start.step = 0;visited[start.x][start.y] = 1;q.push(start);int ans = BFS();if(ans==-1){cout<<"Poor ANGEL has to stay in the prison all his life."<<endl;}else{cout<<ans<<endl;}}return 0;
}

HDU1072
搜索第三题,这题需要一定的模拟技巧,注意好炸弹时间。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int m,n,start_x,start_y;
struct Node{int x,step;int y,time;
};
int map[10][10];
int visited[10][10];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};
queue<Node>q;
int BFS()
{while(!q.empty()){Node p = q.front();q.pop();if(p.time==0){continue;}if(map[p.x][p.y]==3){return p.step;}for(int i = 0;i < 4;i++){int nx = p.x+dx[i];int ny = p.y+dy[i];if(nx<0||nx>=n||ny<0||ny>=m||map[nx][ny]==0){continue;}int step = p.step+1;int time = p.time-1;Node ptr;ptr.x = nx;ptr.y = ny;ptr.step = step;ptr.time = time;if(map[ptr.x][ptr.y]==4&&ptr.time){map[ptr.x][ptr.y] = 1;ptr.time = 6;}q.push(ptr);}}return -1;
}
int main()
{int t;cin>>t;while(t--){cin>>n>>m;for(int i = 0;i < n;i++){for(int j = 0;j < m;j++){cin>>map[i][j];if(map[i][j]==2){start_x = i;start_y = j;}visited[i][j] = 0;}}while(!q.empty()){q.pop();}Node start;start.x = start_x;start.y = start_y;start.step = 0;start.time = 6;q.push(start);int ans = BFS();cout<<ans<<endl;}return 0;
}

POJ3984
搜索第四题,BFS路径打印问题,路径打印方法不止一种,这是我学过最好的路径打印了。网上大部分都借用了stack容器或者递归回溯打印

#include <iostream>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#include <stdio.h>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MAXN 100010
using namespace std;
int mp[10][10],vis[10][10];
int dx[]={0,0,1,-1};
int dy[]={1,-1,0,0};
struct Node{int x,y;int stepx[30],stepy[30],cnt;
}a;
queue<Node>q;
void BFS()
{while(!q.empty()){Node p = q.front(),ptr;q.pop();if(p.x==4&&p.y==4){printf("(0, 0)\n");             //起点 for(int i=0;i<p.cnt;i++)printf("(%d, %d)\n",p.stepx[i],p.stepy[i]);return ;}ptr = p;                      //少了这句话就会错,因为这句话执行了赋值操作。for(int i=0;i<4;++i){ptr.x=p.x+dx[i];ptr.y=p.y+dy[i];if(ptr.x>=0&&ptr.x<=4&&ptr.y>=0&&ptr.y<=4&&vis[ptr.x][ptr.y]==0&&mp[ptr.x][ptr.y]==0){vis[ptr.x][ptr.y]=1;ptr.stepx[ptr.cnt]=ptr.x;ptr.stepy[ptr.cnt++]=ptr.y;q.push(ptr);}} }
}
int main()
{for(int i = 0;i<5;++i){for(int j = 0;j<5;++j){cin>>mp[i][j]; vis[i][j] = 0;}}while(!q.empty()){q.pop();}Node start;start.x = 0;start.y = 0;start.cnt = 0;q.push(start);BFS();return 0;
}

HDU1026
搜索第五题 bfs + priority_queue + 路径打印。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
struct Node{int x,y,s,cnt;int stepx[1015],stepy[1105];bool operator< (const Node &a)const{if(a.s == s){return a.cnt < cnt;}else{return a.s < s;}}
};
char map[1105][1015];
bool visited[1105][1105];
int n,m;
int dx[] = {1,0,-1,0};
int dy[] = {0,1,0,-1};
int BFS()
{priority_queue<Node>q;while(!q.empty()){q.pop();}Node t;t.x = 0;t.y = 0;t.s = 0;t.cnt = 0;t.stepx[0] = 0;t.stepy[0] = 0;visited[t.x][t.y] = true;q.push(t);while(!q.empty()){Node p = q.top();q.pop();if(p.x == n-1 && p.y == m-1){printf("It takes %d seconds to reach the target position, let me show you the way.\n",p.s);int sum = 0;for(int i = 1;i <= p.cnt;i++){printf("%ds:(%d,%d)->(%d,%d)\n",sum+i,p.stepx[i-1],p.stepy[i-1],p.stepx[i],p.stepy[i]);if(map[p.stepx[i]][p.stepy[i]] >= '1' && map[p.stepx[i]][p.stepy[i]] <= '9'){int k = map[p.stepx[i]][p.stepy[i]] - '0';for(int j = 0;j < k;j++){printf("%ds:FIGHT AT (%d,%d)\n",sum+i+1+j,p.stepx[i],p.stepy[i]);}sum += k;}}return 1;}t = p;for(int i = 0;i < 4;i++){t.x = p.x + dx[i];t.y = p.y + dy[i];if(t.x < 0 || t.x >= n || t.y < 0 || t.y >= m || visited[t.x][t.y] == true || map[t.x][t.y] == 'X'){continue;}t.cnt = p.cnt + 1; t.stepx[t.cnt] = t.x;t.stepy[t.cnt] = t.y;t.s = p.s + 1;if(map[t.x][t.y] >= '1' && map[t.x][t.y] <= '9'){t.s = t.s + map[t.x][t.y] - '0';}visited[t.x][t.y] = true;q.push(t);}}return 0;
}
int main()
{while(~scanf("%d%d",&n,&m)){for(int i = 0;i < n;i++){scanf("%s",map[i]);}//    m = strlen(map[0]);memset(visited,false,sizeof(visited));int ans = BFS();if(ans == 0){printf("God please help our poor hero.\n");}printf("FINISH\n");}return 0;
}

HDU1728
搜索第六题 bfs + queue 拐弯问题,解决方法就是一直往一个方向走,走完拐弯数就 + 1。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 110;
struct Node{int x,y,k;
};
queue<Node>q;
int m,n,sx,sy,ex,ey,k;
int visited[maxn][maxn];
char map[maxn][maxn];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
void new_set()
{while(!q.empty()){q.pop();}memset(visited,0,sizeof(visited));
}
bool check(int x,int y)
{if(x >= 1 && x <= m && y >= 1 && y <= n && map[x][y] != '*'){return true;}else{return false;}
}void bfs()
{Node s;s.x = sx;s.y = sy;s.k = -1;q.push(s);visited[sx][sy] = 1; int flag = 0;while(!q.empty()){Node p = q.front();q.pop();if(p.x == ex && p.y == ey && p.k <= k){flag = 1;break;}int sk = p.k + 1; for(int i = 0;i < 4;i++){int nx = p.x + dx[i];int ny = p.y + dy[i];while(check(nx,ny)){if(visited[nx][ny] == 0){Node ptr;ptr.x = nx;ptr.y = ny;ptr.k = sk;visited[nx][ny] = 1;q.push(ptr);}nx += dx[i];ny += dy[i];}}}if(flag == 1){cout<<"yes"<<endl;}else{cout<<"no"<<endl;}
}
int main()
{int t;cin>>t;while(t--){cin>>m>>n;for(int i = 1;i <= m;i++){for(int j = 1;j <= n;j++){cin>>map[i][j];}}cin>>k>>sy>>sx>>ey>>ex;new_set();bfs();}return 0;
}

HDU1241
搜索第七题求联通的个数,bfs + queue。联通的就一次性全部标记好,算跑了几次bfs就知道有几块油田

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn = 105;
struct Node{int x,y;
};
queue<Node>q;
int m,n;
int dx[] = {1,-1,0,0,1,-1,1,-1};
int dy[] = {0,0,1,-1,1,1,-1,-1};
char map[maxn][maxn];
int visited[maxn][maxn];
int check(int x,int y)
{if(map[x][y] == '*' || visited[x][y] == 1 || x <= 0 || x > m || y <= 0 || y > n){return false;}else{return true;}
}
void bfs(int x,int y)
{queue<Node>q;Node p,ptr;p.x = x;p.y = y;q.push(p);while(!q.empty()){p = q.front();q.pop();for(int i = 0;i < 8;i++){ptr.x = p.x + dx[i];ptr.y = p.y + dy[i];if(check(ptr.x,ptr.y) == true){visited[ptr.x][ptr.y] = 1;q.push(ptr);}}}
}
int main()
{while(cin>>m>>n && m&&n){for(int i = 1;i <= m;i++){for(int j = 1;j <= n;j++){cin>>map[i][j];}}memset(visited,0,sizeof(visited));int ans = 0;for(int i = 1;i <= m;i++){for(int j = 1;j <= n;j++){if(visited[i][j] == 0 && map[i][j] == '@'){bfs(i,j);ans++;}}}cout<<ans<<endl;}return 0;
}

HDU1495
搜索第八题之倒水问题,想好转移情况和状态。bfs + queue

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>
using namespace std;
struct node{int s,x,y;int t;
};
const int maxn = 1e6;
bool visited[maxn];
queue<node>q;
void bfs(int s,int n,int m)
{while(!q.empty()){node ptr = q.front(),p;q.pop();if((ptr.s == ptr.x && ptr.s + ptr.x == s) || (ptr.s == ptr.y && ptr.s + ptr.y == s)){printf("%d\n",ptr.t);return ;    }for(int i = 0;i < 6;i++){                    //s,x,y两两互相倒存在6种情况 if(i == 0){                                //s给x倒 if(ptr.x < n && ptr.s > 0){if(ptr.s <= n - ptr.x){            //s中的可乐不够或者刚好够倒满x p.s = 0;p.x = ptr.s + ptr.x;p.y = ptr.y;} else{                            //s中的可乐能够倒满x p.x = n;p.s = ptr.s - (n - ptr.x);p.y = ptr.y;}int t = p.s*10000 + p.x*100 + p.y;if(visited[t] == false){        //判重 visited[t] = true;            //状态标记 p.t = ptr.t + 1;q.push(p);}}}if(i == 1){                                //s给y倒 if(ptr.y < m && ptr.s > 0){if(ptr.s <= m - ptr.y){p.y = ptr.y + ptr.s;p.s = 0;p.x = ptr.x;}else{p.s = ptr.s - (m - ptr.y);p.y = m;p.x = ptr.x;}int t = p.s*10000 + p.x*100 + p.y;if(visited[t] == false){visited[t] = true;p.t = ptr.t + 1;q.push(p);}}}if(i == 2){                    //x给s倒 p.x = 0;p.s = ptr.x + ptr.s;p.y = ptr.y;int t = p.s*10000 + p.x*100 + p.y;if(visited[t] == false){visited[t] = true;p.t = ptr.t + 1;q.push(p);}}if(i == 3){                    //y给s倒 p.x = ptr.x;p.s = ptr.y + ptr.s;p.y = 0;int t = p.s*10000 + p.x*100 + p.y;if(visited[t] == false){visited[t] = true;p.t = ptr.t + 1;q.push(p);} }if(i == 4){                                            //x给y倒if(ptr.y < m && ptr.x > 0){                        //y没满 if(ptr.x <= m - ptr.y){                        //x中的饮料无法填满y p.y = ptr.x + ptr.y;p.x = 0;p.s = ptr.s;}else{p.x = ptr.x - (m - ptr.y);p.y = m;p.s = ptr.s;}int t = p.s*10000 + p.x*100 + p.y;if(visited[t] == false){visited[t] = true;p.t = ptr.t + 1;q.push(p);} }}if(i == 5){                        //y给x倒 if(ptr.x < n && ptr.y > 0){if(ptr.y <= n - ptr.x){p.x = ptr.x + ptr.y;p.y = 0;p.s = ptr.s;}else{p.y = ptr.y - (n - ptr.x);p.x = n;p.s = ptr.s;}int t = p.s*10000 + p.x*100 + p.y;if(visited[t] == false){visited[t] = true;p.t = ptr.t + 1;q.push(p);}}}}}printf("NO\n");
}
int main()
{int s,m,n;while(~scanf("%d%d%d",&s,&n,&m)){if(s == 0 && n == 0 && m == 0){break;}memset(visited,false,sizeof(visited));while(!q.empty()){q.pop();}node p;p.s = s;p.x = 0;p.y = 0;p.t = 0;int t = p.s*10000 + p.x*100 + p.y;visited[t] = true;q.push(p);bfs(s,n,m);}return 0;
}

HDU2612
搜索第九题每个人都单独出发一次bfs,将距离记录在二维数组中,最后找最小

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <queue>
#include <string>
#define maxs 201
#define INF 999999
using namespace std;
char map[maxs][maxs];
int visited[maxs][maxs];
int b[maxs][maxs];
int m,n,y_x,y_y;
int m_x,m_y;
struct Node{int x,y,step;
};
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,-1,1};
queue<Node>q;
void BFS()
{while(!q.empty()){Node p = q.front();q.pop();if(map[p.x][p.y] == '@'){b[p.x][p.y] += p.step;}for(int i = 0;i < 4;i++){int nx = p.x + dx[i];int ny = p.y + dy[i];if(nx<0||nx>=m||ny<0||ny>=n||map[nx][ny] == '#'||visited[nx][ny]==1){continue;}Node ptr;ptr.x = nx;ptr.y = ny;ptr.step = p.step + 1;visited[ptr.x][ptr.y] = 1;q.push(ptr);}}
}
int main()
{while(cin>>m>>n){memset(b,0,sizeof(b));for(int i = 0; i < m; i++){for(int j = 0;j < n; j++){cin>>map[i][j];visited[i][j] = 0;if(map[i][j]=='Y'){y_x = i;y_y = j;}if(map[i][j]=='M'){m_x = i;m_y = j;}}}while(!q.empty()){q.pop();}Node start;start.x = y_x;start.y = y_y;start.step = 0;q.push(start);visited[start.x][start.y] = 1;BFS();while(!q.empty()){q.pop();}memset(visited,0,sizeof(visited));start.x = m_x;start.y = m_y;start.step = 0;q.push(start);visited[start.x][start.y] = 1;BFS();int Min = INF;for(int i = 0;i < m;i++){for(int j = 0;j < n;j++){if(b[i][j]!=0){Min = min(Min,b[i][j]);}}}cout<<Min*11<<endl;}return 0;
}

HDU1195
搜索第十题数字搜索,和上面一样找好转移状态

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
struct Node{int x,step;bool operator <(const Node& s)const{return s.step < step;}
};
priority_queue<Node>q;
int a[4];
bool visited[10001];
void new_set()
{while(!q.empty()){q.pop();}memset(visited,false,sizeof(visited));
}
void bfs(int x,int y)
{Node p;p.x = x;p.step = 0;visited[x] = true;q.push(p);while(!q.empty()){p = q.top();q.pop();if(p.x == y){cout<<p.step<<endl;break;}for(int i = 0;i <= 10;i++){a[0] = p.x/1000;a[1] = p.x/100%10;a[2] = p.x/10%10;a[3] = p.x%10;if(i <= 2){int t = a[i];a[i] = a[i+1];a[i+1] = t;}else if(i <= 6){a[(i+1)%4] += 1;if(a[(i+1)%4] > 9){a[(i+1)%4] = 1;}}else if(i <= 10){a[(i+1)%4] -= 1;if(a[(i+1)%4] <= 0){a[(i+1)%4] = 9;}}Node ptr;ptr.x = a[0]*1000+a[1]*100+a[2]*10+a[3];if(visited[ptr.x] == false){ptr.step = p.step + 1;visited[ptr.x] = true;q.push(ptr);}}}
}
int main()
{int n;cin>>n;while(n--){int x,y;cin>>x>>y;new_set();bfs(x,y);}return 0;
}

HDU1180
搜索第十一题,楼梯会旋转,应该假设你走完一步之后楼梯立马旋转一个方向。然后可以原地等一分钟等楼梯转个方向,第一次卡死在这里。bfs + priotity_queue

#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <queue>
using namespace std;
const int maxn = 25;
struct Node{int x,y,step;bool operator < (const Node &s)const{return s.step < step;}
};
priority_queue<Node>q;
char map[maxn][maxn];
int visited[maxn][maxn];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,1,-1};
int m,n;
void new_set()
{while(!q.empty()){q.pop();}memset(visited,0,sizeof(visited));
}
bool check(int x,int y)
{if(x < 0 || x >= m || y < 0 || y >= n || map[x][y] == '*' || visited[x][y] == 1){return false;}else{return true;}
}
void bfs()
{Node p,ptr;while(!q.empty()){p = q.top();q.pop();if(map[p.x][p.y] == 'T'){cout<<p.step<<endl;break;}for(int i = 0;i < 4;i++){ptr.x = p.x + dx[i];ptr.y = p.y + dy[i];if(check(ptr.x,ptr.y) == false){continue;}if((map[ptr.x][ptr.y] == '|' && p.step % 2 == 0) || (map[ptr.x][ptr.y] == '-' && p.step % 2 == 1)){            if(dx[i] != 0){ptr.x += dx[i];ptr.y += dy[i];if(check(ptr.x,ptr.y) == false){continue;}ptr.step = p.step + 1;visited[ptr.x][ptr.y] = 1;q.push(ptr);}else{ptr.x = p.x;ptr.y = p.y;ptr.step = p.step + 1;q.push(ptr);}}else if((map[ptr.x][ptr.y] == '|' && p.step % 2 == 1)|| (map[ptr.x][ptr.y] == '-' && p.step % 2 == 0)){                if(dy[i] != 0){ptr.x += dx[i];ptr.y += dy[i];if(check(ptr.x,ptr.y) == false){continue;}ptr.step = p.step + 1;visited[ptr.x][ptr.y] = 1;q.push(ptr);}else{ptr.x = p.x;ptr.y = p.y;ptr.step = p.step + 1;q.push(ptr);}}else{visited[ptr.x][ptr.y] = 1;ptr.step = p.step + 1;q.push(ptr);}}}
}
int main()
{int x,y;while(cin>>m>>n){for(int i = 0;i < m;i++){for(int j = 0;j < n;j++){cin>>map[i][j];if(map[i][j] == 'S'){x = i;y = j;}}}new_set();Node start;start.x = x;start.y = y;start.step = 0;q.push(start);visited[x][y] = 1;bfs();}return 0;
}

HDU2717
一维数字搜索,bfs + priority_queue,优不优先队列都可以做

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
using namespace std;
const int maxn = 1e5+10;
struct node{int x;            //当前点的坐标int t;            //时间int z;            //差值绝对值bool operator <(const node s)const{if(s.t == t){return s.z < z;}else{return s.t < t;}}
};
priority_queue<node>q;
bool visited[maxn];
void bfs(int k)
{while(!q.empty()){node p = q.top(),ptr;q.pop();if(p.x == k){printf("0\n");return ;}for(int i = 0;i < 3;i++){if(i == 0){ptr.x = p.x + 1;}if(i == 1){ptr.x = p.x - 1;}if(i == 2){ptr.x = p.x * 2;}if(ptr.x < 0 || ptr.x > maxn || visited[ptr.x] == true){continue;} ptr.t = p.t + 1;if(ptr.x == k){printf("%d\n",ptr.t);return ;}ptr.z = abs(ptr.x - k);visited[ptr.x] = true;q.push(ptr);}}
}
int main()
{int n,k;while(~scanf("%d%d",&n,&k)){memset(visited,false,sizeof(visited));while(!q.empty()){q.pop();}node p;p.x = n;p.t = 0;p.z = abs(k-n);q.push(p);visited[n] = true;bfs(k);}return 0;
}

HDU1973
还是一个开锁问题bfs + queue + 埃筛

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn = 1e5+5;
bool prime[maxn];
bool visited[maxn];
struct node{int num,t;
};
void getprime()
{memset(prime,true,sizeof(prime));prime[0] = prime[1] = false;for(int i = 2;i < maxn;i++){if(prime[i]){for(int j = 2*i;j < maxn;j += i){prime[j] = false;}}}
}
queue<node>q;
void bfs(int y)
{while(!q.empty()){node ptr = q.front(),p;q.pop();if(ptr.num == y){printf("%d\n",ptr.t);return ;}int a[4];a[0] = ptr.num/1000;a[1] = ptr.num/100%10;a[2] = ptr.num/10%10;a[3] = ptr.num%10; //    cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<" "<<a[3]<<endl;for(int i = 0;i < 4;i++){for(int j = 1;j <= 10;j++){if(i == 0){int t = (a[0] + j)%10;int x = t*1000+a[1]*100+a[2]*10+a[3];if(t != a[0] && t != 0 && prime[x] == true && visited[x] == false){p.num = x;p.t = ptr.t + 1;visited[x] = true;q.push(p);}}if(i == 1){int t = (a[1] + j)%10;int x = a[0]*1000+t*100+a[2]*10+a[3];if(t != a[1] && prime[x] == true && visited[x] == false){p.num = x;p.t = ptr.t + 1;visited[x] = true;q.push(p);}}if(i == 2){int t = (a[2] + j)%10;int x = a[0]*1000+a[1]*100+t*10+a[3];if(t != a[2] && prime[x] == true && visited[x] == false){p.num = x;p.t = ptr.t + 1;visited[x] = true;q.push(p);}}if(i == 3){int t = (a[3] + j)%10;int x = a[0]*1000+a[1]*100+a[2]*10+t;if(t != a[3] && prime[x] == true && visited[x] == false){p.num = x;p.t = ptr.t + 1;visited[x] = true;q.push(p);}}}}}
}
int main()
{getprime();int t,x,y;scanf("%d",&t);while(t--){scanf("%d%d",&x,&y);node p;memset(visited,false,sizeof(visited));while(!q.empty()){q.pop();}p.num = x;p.t = 0;q.push(p);visited[x] = true;bfs(y);}    return 0;
}

POJ3414
bfs + queue + 路径打印,还是倒水问题。比杭电那个要简单一点。

#include <iostream>
#include <cstring>
#include <queue>
#include <cstdio>
#include <algorithm>
using namespace std;
struct node{int x,y,t;int f[200];
};
queue<node>q;
bool visited[10000];
void bfs(int a,int b,int c)
{while(!q.empty()){node ptr = q.front(),p;q.pop();if(ptr.x == c || ptr.y == c){printf("%d\n",ptr.t);for(int i = 1;i <= ptr.t;i++){if(ptr.f[i] == 1){printf("FILL(1)\n");}if(ptr.f[i] == 2){printf("FILL(2)\n");}if(ptr.f[i] == 3){printf("DROP(1)\n");}if(ptr.f[i] == 4){printf("DROP(2)\n");}if(ptr.f[i] == 5){printf("POUR(1,2)\n");}if(ptr.f[i] == 6){printf("POUR(2,1)\n");}}return ;}p = ptr;for(int i = 0;i < 6;i++){if(i == 0){               //给a加满 p.x = a;p.y = ptr.y;int t = p.x*100+p.y;if(visited[t] == false){p.t = ptr.t + 1;p.f[p.t] = 1;visited[t] = true;q.push(p);}}if(i == 1){               //给b加满 p.x = ptr.x;p.y = b;int t = p.x*100+p.y;if(visited[t] == false){p.t = ptr.t + 1;p.f[p.t] = 2;visited[t] = true;q.push(p);}}if(i == 2){               //把a倒掉 p.x = 0;p.y = ptr.y;int t = p.x*100+p.y;if(visited[t] == false){p.t = ptr.t + 1;p.f[p.t] = 3;visited[t] = true;q.push(p);}}if(i == 3){               //把b倒掉 p.x = ptr.x;p.y = 0;int t = p.x*100+p.y;if(visited[t] == false){p.t = ptr.t + 1;p.f[p.t] = 4;visited[t] = true;q.push(p);}}if(i == 4){               //a给b倒 if(ptr.y < b){if(ptr.x <= b - ptr.y){p.x = 0;p.y = ptr.x + ptr.y;}else{p.x = ptr.x - (b - ptr.y);p.y = b;}int t = p.x*100+p.y;if(visited[t] == false){p.t = ptr.t + 1;p.f[p.t] = 5;visited[t] = true;q.push(p);}}}if(i == 5){              //b给a倒 if(ptr.x < a){if(ptr.y <= a - ptr.x){p.x = ptr.x + ptr.y;p.y = 0;}else{p.x = a;p.y = ptr.y - (a - ptr.x);}int t = p.x*100+p.y;if(visited[t] == false){p.t = ptr.t + 1;p.f[p.t] = 6;visited[t] = true;q.push(p);}}}}}printf("impossible\n");
}
int main()
{int a,b,c;while(~scanf("%d%d%d",&a,&b,&c)){while(!q.empty()){q.pop();}node p;p.x = 0;p.y = 0;p.t = 0;memset(p.f,0,sizeof(p.f));memset(visited,0,sizeof(visited));q.push(p);bfs(a,b,c);}return 0;
}

POJ2251
简简单单一个三维迷宫,bfs + queue

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
struct Node{int x,y,z,step;
};
const int maxn = 35;
int dx[] = {1,-1,0,0,0,0};
int dy[] = {0,0,1,-1,0,0};
int dz[] = {0,0,0,0,1,-1};
char map[maxn][maxn][maxn];
queue<Node>q;
int x,y,z;
int bfs()
{while(!q.empty()){Node ptr = q.front(),p;q.pop();for(int i = 0;i < 6;i++){p.x = ptr.x + dx[i];p.y = ptr.y + dy[i];p.z = ptr.z + dz[i];if(p.x < 0 || p.x >= x || p.y < 0 || p.y >= y || p.z < 0 || p.z >= z || map[p.x][p.y][p.z] == '#'){continue;       }p.step = ptr.step + 1;if(map[p.x][p.y][p.z] == 'E'){return p.step;}map[p.x][p.y][p.z] = '#';q.push(p);}}return -1;
}
int main()
{while(~scanf("%d%d%d",&x,&y,&z)){    int start_x,start_y,start_z;if(x == 0 && y == 0 && z == 0){break;}int flag = 0;for(int i = 0;i < x;i++){for(int j = 0;j < y;j++){scanf("%s",map[i][j]);if(flag == 1){continue;}int len = strlen(map[i][j]);for(int k = 0;k < len;k++){if(map[i][j][k] == 'S'){start_x = i;start_y = j;start_z = k;flag = 1;break;}}}}while(!q.empty()){q.pop();}Node start;start.x = start_x;start.y = start_y;start.z = start_z;start.step = 0;q.push(start);int ans = bfs();if(ans == -1){printf("Trapped!\n");}else{printf("Escaped in %d minute(s).\n",ans);}}return 0;
}

最后一道可能交不了UVA11624,可以去VJ上交。
这道题应该是和前面HDU2612差不多,先让火跑bfs把到达每一块空地的时间存下来,然后让人去跑bfs看看能不能比火先到这个点,如果能就可以过去,如果人走到这里比火还慢,对不起等着被烧死。注意有多个起火点,WA了一发不冤。

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int inf = 1e9;
const int maxn = 1050;
struct node{int x,y;int s;
};
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
char map[maxn][maxn];
bool visited[maxn][maxn];
int sum[maxn][maxn];
queue<node> q;
void clear_queue()
{memset(visited,false,sizeof(visited));while(!q.empty()){q.pop();}
}
void bfs_fire(int m,int n)
{while(!q.empty()){node ptr = q.front(),p;q.pop();for(int i = 0;i < 4;i++){p.x = ptr.x + dx[i];p.y = ptr.y + dy[i];p.s = ptr.s + 1;if(p.x < 0 || p.x >= m || p.y < 0 || p.y >= n || map[p.x][p.y] == 'F' || map[p.x][p.y] == '#' || visited[p.x][p.y]){continue;}sum[p.x][p.y] = p.s;visited[p.x][p.y] = true;q.push(p);}}
}
int bfs_person(int m,int n)
{while(!q.empty()){node ptr = q.front(),p;q.pop();if(ptr.x == 0 || ptr.y == 0 || ptr.x == m-1 || ptr.y == n-1){return ptr.s + 1;}for(int i = 0;i < 4;i++){p.x = ptr.x + dx[i];p.y = ptr.y + dy[i];p.s = ptr.s + 1;if(map[p.x][p.y] == '#' || map[p.x][p.y] == 'F' || p.s >= sum[p.x][p.y] || visited[p.x][p.y]){continue;}visited[p.x][p.y] = true;q.push(p);}}  return -1;
}
int main()
{int t,m,n;node p;cin>>t;while(t--){clear_queue();cin>>m>>n; int p_x,p_y;for(int i = 0;i < m;i++){for(int j = 0;j < n;j++){cin>>map[i][j];if(map[i][j] == 'J'){p_x = i;p_y = j;}if(map[i][j] == 'F'){p.x = i;p.y = j;p.s = 0;visited[p.x][p.y] = true;q.push(p);}sum[i][j] = inf;}}bfs_fire(m,n);clear_queue();p.x = p_x;p.y = p_y;p.s = 0;visited[p.x][p.y] = true;q.push(p);int ans = bfs_person(m,n);if(ans == -1){printf("IMPOSSIBLE\n");}else{printf("%d\n",ans);}}return 0;
}

HDU1175
bfs+queue,拐弯问题。先一直死走一个方向走完就一定要拐弯数+1,这题和上面那个挺像的。第二次接触拐弯问题在WA两发情况下AC了,开始两发考虑的不全

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int maxn = 1005;
struct info{int x,y;int s;
};
int map[maxn][maxn];
bool visited[maxn][maxn];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,-1,1};
queue<info>q;
int n,m;
int check(int x,int y)
{if(x >= 1 && x <= n && y >= 1 && y <= m){return true;}else{return false;}
}
int bfs(int x,int y,int a,int b,int num)
{info ptr,p;ptr.x = x;ptr.y = y;ptr.s = -1;visited[x][y] = true;q.push(ptr);while(!q.empty()){ptr = q.front();q.pop();if(ptr.s > 2){                //大于2的拐弯直接掐掉,我感觉应该加入优先队列优化。continue;}if(ptr.x == a && ptr.y == b){       //这里可以删掉了return 1;}int sk = ptr.s + 1;for(int i = 0;i < 4;i++){p.x = ptr.x + dx[i];p.y = ptr.y + dy[i];while(check(p.x,p.y) == true){if(visited[p.x][p.y] == false){if(p.x == a && p.y == b){       if(sk <= 2){            //这个点是终点可以还要判断能不能拐弯数是不是不超过2return 1;            //因为上面只是筛掉了大于2的,等于2的没有筛掉}}else if(map[p.x][p.y] == 0){ //如果不是终点但是是空点可以走,入队visited[p.x][p.y] = true;p.s = sk;q.push(p);}}if(map[p.x][p.y] != 0){          //如果上一个点不是终点又不是空点这个方向就不用一直走了break;}p.x += dx[i];p.y += dy[i];}}}return -1;
}
void clear_set()
{memset(visited,false,sizeof(visited));while(!q.empty()){q.pop();}
}
int main()
{while(~scanf("%d%d",&n,&m) && n && m){memset(map,0,sizeof(map));for(int i = 1;i <= n;i++){for(int j = 1;j <= m;j++){scanf("%d",&map[i][j]);}}int q;scanf("%d",&q);while(q--){int x,y,a,b;scanf("%d%d%d%d",&x,&y,&a,&b);clear_set();if(map[x][y] != map[a][b] || !map[x][y] || (x == a && y == b)){      //小小的剪枝printf("NO\n");continue;}int ans = bfs(x,y,a,b,map[x][y]);if(ans == -1){printf("NO\n");}else{printf("YES\n");}}}return 0;
}

HDU2822
bfs + 优先队列,模板题。。。。。。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 1005;
struct info{int x,y;int s;bool operator<(const info a)const{return a.s < s;}
};
priority_queue<info>q;
char map[maxn][maxn];
bool visited[maxn][maxn];
int dx[] = {1,-1,0,0};
int dy[] = {0,0,-1,1};
int n,m;
void clear_set()
{memset(visited,false,sizeof(visited));while(!q.empty()){q.pop();}
}
void bfs(int x,int y)
{info p,ptr;while(!q.empty()){ptr = q.top();q.pop();if(ptr.x == x && ptr.y == y){printf("%d\n",ptr.s);break;}for(int i = 0;i < 4;i++){p.x = ptr.x + dx[i];p.y = ptr.y + dy[i];p.s = ptr.s;if(p.x < 0 || p.x >= m || p.y < 0 || p.y >= n || visited[p.x][p.y]){continue;}visited[p.x][p.y] = true;if(map[p.x][p.y] == '.'){p.s += 1;}q.push(p);}}
}
int main()
{    while(~scanf("%d%d",&m,&n) && m && n){clear_set();for(int i = 0;i < m;i++){scanf("%s",map[i]);}info p;int x,y;scanf("%d%d",&x,&y);p.x = x - 1;p.y = y-1;p.s = 0;visited[p.x][p.y] = true;q.push(p);scanf("%d%d",&x,&y);bfs(x-1,y-1);}return 0;
}

基础bfs搜索就这样了,当然还有难的,需要结合状态压缩等等目前自己还不会,加油~

搜索入门之BFS宽度优先搜索相关推荐

  1. 【算法入门】广度/宽度优先搜索(BFS)

    广度/宽度优先搜索(BFS) [算法入门] 郭志伟@SYSU:raphealguo(at)qq.com 2012/04/27 1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述) ...

  2. 【BFS宽度优先搜索】

    一.求所有顶点到s顶点的最小步数   1 //BFS宽度优先搜索 2 #include<iostream> 3 using namespace std; 4 #include<que ...

  3. 算法笔记01——深度优先搜索(DFS)/宽度优先搜索(BFS)

    深度优先搜索(DFS) 从某个状态开始,不断地转移状态直到无法转移,然后回退到前一步的状态,继续转移到其他状态,如此不断重复,直至找到最终的解.深度优先搜索从最开始的状态出发,遍历所有可以到达的状态. ...

  4. 188. 武士风度的牛 C++ bfs(宽度优先搜索)

    农民John有很多牛,他想交易其中一头被Don称为The Knight的牛. 这头牛有一个独一无二的超能力,在农场里像Knight一样地跳(就是我们熟悉的象棋中马的走法). 虽然这头神奇的牛不能跳到树 ...

  5. 广度/宽度优先搜索(BFS)详解

    1.前言 广度优先搜索(也称宽度优先搜索,缩写BFS,以下采用广度来描述)是连通图的一种遍历策略.因为它的思想是从一个顶点V0开始,辐射状地优先遍历其周围较广的区域,故得名. 一般可以用它做什么呢?一 ...

  6. 层层递进——宽度优先搜索(BFS)

    问题引入 我们接着上次"解救小哈"的问题继续探索,不过这次是用宽度优先搜索(BFS). 注:问题来源可以点击这里 http://www.cnblogs.com/OctoptusLi ...

  7. BFS(宽度优先搜索、广度优先搜索)

    宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型.Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想.其别名又 ...

  8. 图/树——宽度优先搜索(BFS)

    转载 宽度优先搜索(BFS, Breadth First Search)是一个针对图和树的遍历算法.发明于上世纪50年代末60年代初,最初用于解决迷宫最短路径和网络路由等问题. 对于下面的树而言,BF ...

  9. 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS)

    广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first search,BFS) 1. 广度优先搜索 - 宽度优先搜索 - 横向优先搜索 (breadth-first searc ...

最新文章

  1. 3310复刻版 java_终于等到你:诺基亚3310复刻版开箱简评
  2. 使用nio多线程下载网络文件实例
  3. python替换字符的操作_Python 字符串操作(string替换、删除、截取、复制、)
  4. nssl1469-W【dp】
  5. Ethercat解析(十三)之fsm_master状态机
  6. 【从0到1,搭建Spring Boot+RESTful API+Shiro+Mybatis+SQLServer权限系统】05、Shiro集成
  7. 邻接矩阵存储图的深度优先遍历
  8. 计算机图形学考试题及答案_中国大学 MOOC_计算机图形学_测试题及答案
  9. jmstudio 摄像头获取不到_什么是全景摄像头?
  10. 【实习之T100开发】T100程序功能代码积累
  11. 20200909:链表类题目集合下
  12. AS3之BitmapData学习整理
  13. 爬虫cookie过期_【Python】Scrapy爬虫框架之Request和Response
  14. Node js模块系统
  15. 京东全链路压测军演系统(ForceBot)架构解密
  16. Ms08067联合360漏洞响应平台(SRC)送给白帽子20本“精选的10本安全好书”
  17. 监督管理计算机系统的安全保,网络信息安全知识:监督管理计算机信息系统安全保护工作应由()完成。...
  18. 想从事区块链开发? 你应该这么做
  19. 电脑版美食大战老鼠放置html,美食大战老鼠电脑版
  20. Android项目必备技术

热门文章

  1. python网络安全实战_Python安全攻防:渗透测试实战指南
  2. linux的关机与重启
  3. 别瞎搞了!微博、知乎就是这么设计Feed流系统的~
  4. Linux C/C++网络编程实战-陈硕-笔记3-回顾基础的 Sockets API
  5. Windows下硬盘安装Ubuntu Linux
  6. java 俄罗斯方块简易_Java实现简易俄罗斯方块
  7. [转]诺基亚的反击战
  8. CCriticalSection临界区的使用方法
  9. 【华为机试真题 Python实现】寻找身高相近的小朋友
  10. 【金杯至尊】之罗罗的天空----图忆1994世界杯