poj3083——Children of the Candy Corn

题目大意:从迷宫入口S走到出口E,可以沿着人物当前左手边的墙走,也可以沿着右手边的墙走,问分别经过的方块个数,以及S到E的最短路径

输入:迷宫个数n

           迷宫宽度(列数)w 迷宫高度(行数)h (w>=3,h<=40)

           第i行迷宫的布局(#表示墙 .表示空路,迷宫四面除了入口S和出口E都是墙,SE至少间隔一个墙,且不在角落)

输出:(第i个迷宫) 沿着左边墙走经过的方块个数  沿着右边墙走经过的方块个数  S到E所经过方块的最短路

分析:前两问用dfs,最后一问是bfs

           (一)先说dfs

            沿着左边墙走的dfs顺序为左上右下,方向数组为:← ↑ → ↓ 0 1 2 3

            沿着右边墙走的dfs顺序为右上左下,方向数组为: →↑ ← ↓ 0 1 2 3

            dl、dr分别为沿着左边墙和沿着右边墙走时,行列坐标的变化数组

            深度优先搜索函数dfs(sx,sy,d1/d2,1,dl/dr):意味着以(sx,sy)为当前起点,以d为当前方向,步数为1开始递归搜索

            d1、d2表示当前方向,d1是沿着左手边的墙走,d2是沿着右手边的墙走

            每次dfs分别转向四个方向,判断向这个方向走一步是否能走,越界或撞墙就换方向,到终点就退出,否则就意味着能走,继续dfs

            (二)再说bfs

            求最短路径,用队列bfs,注意添加vis[][]数组辅助判断是否已经访问过该位置

            不断从队列中弹出结点,以弹出结点为当前起始位置,判断是否到达终点,已到达就退出,没到达就bfs转向四个方向,判断这个方向走一步是否能走,越界、撞墙或已经走过这个位置就换方向,否则就意味着能走,将这个位置入队

代码:转载自https://www.cnblogs.com/shenben/p/5628296.html

#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 node{
    int x,y,s;
    node (int x=0,int y=0,int s=0):x(x),y(y),s(s){}
};
int dfs(int x,int y,int d,int step,int dir[][2]) {
    for(int i=0;i<4;i++){
        int j=((d-1+4)%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<node>que;
    que.push((node){sx,sy,1});
    vis[sx][sy]=true;
    while(!que.empty()) {
        node p=que.front();que.pop();
        if(p.x==ex&&p.y==ey) return p.s;
        node 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;
                que.push(np);
            }
        }
    }
    return -1;
}
int main() 
{
    int T,d1,d2;
    scanf("%d",&T);
    while(T--) {
        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;}//由于沿着左边墙和沿着右边墙走的方向数组不同,d1d2不同
        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 ",dfs(sx,sy,d1,1,dl));
        printf("%d ",dfs(sx,sy,d2,1,dr));
        printf("%d\n",bfs(sx,sy));
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值