搜索入门之BFS宽度优先搜索

基础搜索入门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){			//这个点是终点可以还要判断能不能拐弯数是不是不超过2
							return 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;
}

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

发布了8 篇原创文章 · 获赞 3 · 访问量 381

猜你喜欢

转载自blog.csdn.net/weixin_43808717/article/details/104619203