【BFS】【DFS】盲人摸象

在这里插入图片描述
在这里插入图片描述
数据范围 n,m<=40;

比赛想法:
感觉好麻烦,转来转去的,恶心死了;
归根到底,是这种题目写的太少,还有不够静下心来。

#include <iostream> 
#include <cstdio> 
#include <cstring> 
#include <cstdlib> 
#include <queue> 
using namespace std; 
const int maxn = 100+10; 
int dx[] = {0, -1, 0, 1}; 
int dy[] = {-1, 0, 1, 0}; 
int dl[][2] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}}; 
int dr[][2] = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}}; 
int sx, sy, ex, ey, n, m; 
char G[maxn][maxn]; 
struct Pos { int x, y, s; };
int dfs(int x, int y, int d, int step, int dir[][2]) { 
    for(int i=0; i<4; i++) { 
        int j = ((d+3)%4+i)%4; 
        int nx = x+dir[j][0]; 
        int ny = y+dir[j][1]; 
        if(nx == ex && ny == ey) return step+1; 
        if(nx < 0 || ny < 0 || nx > n || ny > m) continue; 
        if(G[nx][ny] == '#') continue; 
        return dfs(nx, ny, j, step+1, dir); 
    } 
}
int BFS(int sx, int sy) { 
    bool vis[maxn][maxn]; 
    memset(vis, false, sizeof(vis)); 
    queue<Pos> Q; 
    Q.push((Pos){sx, sy, 1}); 
    vis[sx][sy] = true; 
    while(!Q.empty()) { 
        Pos p = Q.front(); Q.pop(); 
        if(p.x == ex && p.y == ey) return p.s; 
        Pos np;
		for(int d=0; d<4; d++) { 
            np.x = p.x + dx[d]; 
            np.y = p.y + dy[d]; 
            np.s = p.s + 1; 
            if(np.x < 0 || np.x > n || np.y < 0 || np.y > m) continue; 
            if(vis[np.x][np.y]) continue; 
            if(G[np.x][np.y] != '#') { 
                vis[np.x][np.y] = true; 
                Q.push(np); 
            } 
        } 
    }
    return -1; 
}
int main() { 
    int d1, d2; 
    scanf("%d%d", &m, &n); 
    for(int i=0; i<n; i++) { 
        scanf("%s", G[i]); 
        for(int j=0; j<m; j++) { 
            if(G[i][j] == 'S') { 
                sx = i; sy = j; 
            } else if(G[i][j] == 'E') { 
                ex = i; ey = j; 
            } 
        } 
    }
    if(sx == 0) { 
        d1 = 3; d2 = 3; 
    } else if(sx == n-1) { 
        d1 = 1; d2 = 1; 
    } else if(sy == 0) { 
        d1 = 2; d2 = 0; 
    } else if(sy == m-1) { 
        d1 = 0; d2 = 2; 
    } 
    printf("%d\n", dfs(sx, sy, d1, 1, dl)); 
    printf("%d\n", dfs(sx, sy, d2, 1, dr)); 
    printf("%d\n", BFS(sx, sy)); 
    return 0; 
}

题解:
如果是正常人的话,那就是最普通的bfs;只不过结构体里再存一个步数罢了。
至于左撇子盲人和右撇子盲人呢,就按照他的规则来走就好了。
这道题的难点就是静下心来,排出坐标的转换。
这里用了两个d1,d2,存储人的朝向,实际上两个不管是左撇子,右撇子,他们的朝向都是一样的。
在这里插入图片描述
但是因为他们转的方向不一样,所以他们的方向数组顺序也就不一样,所以同一个朝向在数组里的位置也不一样,所以d1,d2也就不一样.

同时,需要注意的是,竖轴是x,横轴是y,而且如果往上走,应该是x-1,y不变,即{-1,0},其余的也同理。

还有,则是这道题的题意没有给的很清晰,也就是初始的点只可能在矩形的四条边上,因为初始的点即房间的门~

整个程序里有两步比较关键:
1,
int dl[][2] = {{0, -1}, {-1, 0}, {0, 1}, {1, 0}};
int dr[][2] = {{0, 1}, {-1, 0}, {0, -1}, {1, 0}};

上面的数组是左撇子的,取当前朝向的前一个开始,往后数四个。
就比如现在的d1是1,也就是当前的方向是往上的,那么就是从下标0开始再到3;因为先看左边是否可以走,如果左边不能走就看当前朝向能不能走,如果左边上面都堵了,就只能往右,如果右边也堵了,就只能原路返回了。实际上就是模拟了这么一个过程。

2,
int j = ((d+3)%4+i)%4;
就是在草稿纸上推一下,
这样的公式才能使初始位置是当前朝向的前一个下标。

发布了62 篇原创文章 · 获赞 0 · 访问量 667

猜你喜欢

转载自blog.csdn.net/weixin_44745441/article/details/104712439
今日推荐