poj3083——Children of the Candy Corn

来源:互联网 发布:女排比赛直播软件 编辑:程序博客网 时间:2024/06/04 01:02

题目大意:从迷宫入口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;}