POJ 3083 Children of the Candy Corn (DFS+BFS)

题目链接:http://poj.org/problem?id=3083

题目大意:给你一个迷宫,S是起点,E是终点,#是墙,.是路,S、E在迷宫的边界,并且有唯一解;求优先左转S到E的步数,优先右转S到E的步数,以及S到E的最短步数。

题解:

1、本题的难点在于左转优先以及右转优先,下一步的方向取决于当前位置的方向,用DFS不断的按优先方向遍历一遍迷宫即可;我定义如图:

  前(0)  
左(1) 当前位置方向(dir) 右(3)
  后(2)  

以左转优先为例,便利迷宫的方向依次为:左、前、右、后;即:

左:(dir+1)%4

前;(dir+0)%4

右:(dir+3)%4

后:(dir+2)%4

右转优先只要改变一下遍历方向即可;

2、求S到E的最短路用BFS遍历即可;

*具体看代码注释

#include <iostream>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;

struct point
{
    int x,y,step;
};
char map[50][50];
queue<point>q;
int n,m;
int lstep,rstep;
int go[4][2]={-1,0,0,-1,1,0,0,1};//四个方向,按左、前、右、后存储

int is_way(int x,int y)//判断此点是否可走
{
    if(x<0 || x>=n || y<0 || y>=m || map[x][y]==‘#‘)
        return 0;
    return 1;
}

void ldfs(int x,int y,int dir)//左转优先,x,y记录当前位置,dir记录当前方向
{
    lstep++;//步数
    //cout<<x<<‘ ‘<<y<<‘ ‘<<fx<<endl;
    //getchar();
    if(map[x][y]==‘E‘) return;//找到终点退出
    if( is_way(x+go[(dir+1)%4][0],y+go[(dir+1)%4][1]) )//左转
        ldfs( x+go[(dir+1)%4][0], y+go[(dir+1)%4][1], (dir+1)%4 );
    else if( is_way(x+go[(dir)%4][0],y+go[(dir)%4][1]) )//前走
        ldfs( x+go[(dir)%4][0], y+go[(dir)%4][1], (dir)%4 );
    else if( is_way(x+go[(dir+3)%4][0],y+go[(dir+3)%4][1]) )//右转
        ldfs( x+go[(dir+3)%4][0], y+go[(dir+3)%4][1], (dir+3)%4 );
    else ldfs( x+go[(dir+2)%4][0], y+go[(dir+2)%4][1], (dir+2)%4 );//后退
}

void rdfs(int x,int y,int dir)//右转优先
{
    rstep++;
    if(map[x][y]==‘E‘) return;
    if( is_way(x+go[(dir+3)%4][0],y+go[(dir+3)%4][1]) )//右转
        rdfs( x+go[(dir+3)%4][0], y+go[(dir+3)%4][1], (dir+3)%4 );
    else if( is_way(x+go[(dir)%4][0],y+go[(dir)%4][1]) )//前走
        rdfs( x+go[(dir)%4][0], y+go[(dir)%4][1], (dir)%4 );
    else if( is_way(x+go[(dir+1)%4][0],y+go[(dir+1)%4][1]) )//左转
        rdfs( x+go[(dir+1)%4][0], y+go[(dir+1)%4][1], (dir+1)%4 );
    else rdfs( x+go[(dir+2)%4][0], y+go[(dir+2)%4][1], (dir+2)%4 );//后退
}

int bfs()//求S到E最短距离,BFS模板即可
{
    while(!q.empty())
    {
        point p=q.front();
        q.pop();
        for(int i=0;i<4;i++)
        {
            int x=p.x+go[i][0];
            int y=p.y+go[i][1];
            if(map[x][y]==‘E‘) return p.step+1;
            if(is_way(x,y))
            {
                point temp;
                temp.x=x;
                temp.y=y;
                temp.step=p.step+1;
                q.push(temp);
                map[x][y]=‘#‘;
            }
        }
    }
    return 0;
}

int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        while(!q.empty())
            q.pop();
        int x,y;
        cin>>m>>n;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
            {
                cin>>map[i][j];
                if(map[i][j]==‘S‘)
                {
                    x=i;
                    y=j;
                }
            }
        lstep=0;
        rstep=0;
        ldfs(x,y,0);
        rdfs(x,y,0);
        point p;
        p.x=x;
        p.y=y;
        p.step=1;
        q.push(p);
        map[x][y]=‘#‘;
        cout<<lstep<<‘ ‘<<rstep<<‘ ‘<<bfs()<<endl;
    }
    return 0;
}

后:(dir+2)%4

时间: 2024-12-28 11:27:40

POJ 3083 Children of the Candy Corn (DFS+BFS)的相关文章

POJ 3083 -- Children of the Candy Corn(DFS+BFS)TLE

POJ 3083 -- Children of the Candy Corn(DFS+BFS) 题意: 给定一个迷宫,S是起点,E是终点,#是墙不可走,.可以走 1)先输出左转优先时,从S到E的步数 2)再输出右转优先时,从S到E的步数 3)最后输出S到E的最短步数 解题思路: 前两问DFS,转向只要控制一下旋转方向就可以 首先设置前进方向对应的数字 向上--N--0 向右--E--1 向下--S--2 向左--W--3 比如说右转优先,即为向右,向前,向左,向后,即逆时针方向for(int i

POJ 3083:Children of the Candy Corn(DFS+BFS)

Children of the Candy Corn Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9311 Accepted: 4039 Description The cornfield maze is a popular Halloween treat. Visitors are shown the entrance and must wander through the maze facing zombies, ch

POJ 3083 Children of the Candy Corn(顺时针DFS+逆时针DFS+BFS)

题目链接:POJ 3083 Children of the Candy Corn [题意]给出一个迷宫,不超过40*40,'#'代表墙,'.'代表能走,'S'是起点,'E'是终点.分别求出从起点一直沿左走,一直沿右走,走到终点所需要的步数.以及走出迷宫的最小步数. [思路]首先最小步数很简单,一个普通BFS搞定,这道题重点是一直向左走和一直向右走的DFS的方向问题,方向还和游客当时朝向有关.开始一直认为是每次都向左(右)转,直到可以走,然后就一直不对,在google了之后才知道向左走要遵循左上右

POJ 3083 Children of the Candy Corn(搜索)

Children of the Candy Corn Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10975   Accepted: 4731 Description The cornfield maze is a popular Halloween treat. Visitors are shown the entrance and must wander through the maze facing zombie

POJ 3083 Children of the Candy Corn

Children of the Candy Corn Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: 308364-bit integer IO format: %lld      Java class name: Main The cornfield maze is a popular Halloween treat. Visitors are shown the

poj 3083 Children of the Candy Corn(bfs+dfs)

Children of the Candy Corn Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10739   Accepted: 4626 Description The cornfield maze is a popular Halloween treat. Visitors are shown the entrance and must wander through the maze facing zombie

POJ 3083 Children of the Candy Corn (DFS + BFS + 模拟)

题目链接:http://poj.org/problem?id=3083 题意: 这里有一个w * h的迷宫,给你入口和出口,让你分别求以下三种情况时,到达出口的步数(总步数包括入口和出口): 第一种:当你需要选择下一个位置时,总是需要这么考虑:如果当前的左方能走,那么就走左方;否则考虑前方是否能走,如果能走,那么就选前方;否则考虑右方是否能走,如果可以,就走右方.如果不能就返回上一个位置,即当前位置的后方.总结下来选择道路的优先顺序为(以当前所处方位为准) 左 -> 上(前) -> 右 -&g

搜索模板(DFS/BFS)

DFS int b[4][2] = {-1,0,0,1,1,0,0,-1}; int DFS( pair<int,int> x ) { int res=0; visited[x.first][x.second]=1; for( int i=0;i<4;i++ ){ pair<int,int> tmp; tmp.first=x.first+b[i][0]; tmp.second=x.second+b[i][1]; if( check(tmp) ) { visited[tmp.f

POJ-3083 Children of the Candy Corn (BFS+DFS)

Description The cornfield maze is a popular Halloween treat. Visitors are shown the entrance and must wander through the maze facing zombies, chainsaw-wielding psychopaths, hippies, and other terrors on their quest to find the exit. One popular maze-