POJ 3083_Children of the Candy Corn

题意:

给定迷宫图,求出一个人从入口进,从出口出,所走过的最短路径以及分别沿着左手边和右手边的墙走出迷宫所走过的方格数。

分析:

  • bfs求最短路
  • 对于沿左右两边的墙走的情况,记录好行走的方向及相对应的左/右边墙的方向坐标
  • 注意判断前方和左/右是否为墙,若前方为墙,则进行逆时针旋转,若左/右方不为墙,则应直接向左/右方向走。
  • 注意考虑前方和左/右边坐标不在迷宫内的情况。

代码:

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#include<queue>
using namespace std;
const int maxn =55;
int w, h, cnt = 1;
int ei, ej, si, sj;
char c[maxn][maxn];
int d[maxn][maxn];
typedef pair<int, int> pii;
pii t[4];
map<pii,pii>m[2];
int in(int x, int y)
{
    if(0<=x&&x<h&&0<=y&&y<w) return 1;
    else return 0;
}
void dfs(int x,int y, pii dir, int a)
{
    if(x==ei&&y==ej) return ;
    pii temp=m[a][dir];
    if(in(x+temp.first, y+temp.second)&&c[x+temp.first][y+temp.second]=='#'){
           if(in(x+dir.first, y+dir.second)&&c[x+dir.first][y+dir.second]!='#'&&c[x+dir.first][y+dir.second]!='S') {
             //   cout<<x+dir.first<<' '<<y+dir.second<<endl;
                cnt++;
                dfs(x+dir.first, y+dir.second,dir,a);
            }else  dfs(x, y,m[1-a][dir],a);
    }else{
        if(in(x+temp.first, y+temp.second)){
        //    cout<<p.x+temp.first<<' '<<p.y+temp.second<<endl;
            cnt++;
            dfs(x+temp.first, y+temp.second, temp,a);
        }else dfs(x, y,m[1-a][dir],a);
    }
    return ;
}
void bfs()
{
    queue<pii>q;
    q.push(make_pair(si, sj));
   memset(d, 0,sizeof(d));
   d[si][sj]=1;
   while(!q.empty()){
        pii temp = q.front();q.pop();
        if(temp.first == ei&&temp.second == ej) break;
        for(int i = 0; i < 4; i++){
            int x = temp.first+t[i].first, y = temp.second+t[i].second;
            if(in(x, y)&&c[x][y]!='#'&&d[x][y] ==0){
                q.push(make_pair(x,  y));
                d[x][y]=d[temp.first][temp.second]+1;
            }
        }
    }
    return;
}
int main (void)
{
    int n;scanf("%d",&n);
    t[0]=make_pair(-1,0);t[1]=make_pair(0,1);t[2]=make_pair(1,0);t[3]=make_pair(0,-1);
    for(int i = 0; i < 4; i++){
        m[0][t[i]]=t[(i+3)%4];
        m[1][t[i]]=t[(i+1)%4];
    }
    while(n--){
        cnt = 1;
        scanf("%d%d",&w,&h);
        for(int i = 0; i < h;i++){
                scanf("%s",c[i]);
            for(int j = 0; j < w; j++){
                if(c[i][j]=='S') si = i, sj = j;
                if(c[i][j]=='E') ei = i, ej = j;
            }
        }
        dfs(si,sj,t[0],0);
        printf("%d ",cnt);
        cnt = 1;
        dfs(si,sj,t[0],1);
        printf("%d ",cnt);
        bfs();
        printf("%d\n",d[ei][ej]);
    }

}

转载于:https://www.cnblogs.com/Tuesdayzz/p/5758841.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值