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

本文介绍了一个迷宫寻路问题的解决方法,包括绕墙向左和向右的深搜算法及寻找最短路径的广搜算法。通过具体的代码示例展示了如何实现这些算法。

http://poj.org/problem?id=3083

(1)求绕墙向左走,绕墙向右走,最短路分别是多少。前两个深搜,最后一个广搜(墙不能走)。

(2)本题的广搜是最基本的搜索,很简单。但我用了优先队列(虽然可以用,但并不需要),而且将优先队列写错了。。

friend bool operator <(node a, node b)
{
    return a.step<b.step;
}

       这是求“最长路”,而不是求最短路。应该是:

friend bool operator <(node a, node b)
{
    return a.step>b.step;
}

(3)走路的顺序是有讲究的,在图上恰好是顺时针(或逆时针)一圈:

int dir[4][2]={-1,0,0,1,1,0,0,-1};

    左是指前一次走的方向的左边,故有:

for(i=p-1;i<=p+2;i++)
{
    j=(i%4+4)%4;
    ...
}

      同理,向右走是指前一次方向的右边:

for(i=p+1;i>=p-2;i--)
{
    j=(i%4+4)%4;
    ...
}

     当然,衍生的写法还有很多种。这里有一种神奇的写法:

for(i=p-1;i<=p+2;i++)
{
    j=(8+i)&3;
    ...
}

     虽然不容易懂,但本质上还是对4取余数。

具体代码:

View Code
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
char map[45][45];
int mark[45][45];
int px, py, ex, ey, pp, flag;
int n, m, t;
int dir[4][2]={-1,0,0,1,1,0,0,-1};
int left_step, right_step, min_step;
struct node
{
    int x, y, step, road;
}e, s;
void start()
{
    int i;
    for(i=0;i<4;i++)
    {
        int tx, ty;
        tx=px+dir[i][0];
        ty=py+dir[i][1];
        if(tx>=0&&tx<n&&ty>=0&&ty<m&&map[tx][ty]!='#')
            {pp=i; break;}
    }
}
int dfs_left(int x, int y, int p)
{
    int i, j;
    if(map[x][y]=='E') return 1;
    for(i=p-1;i<=p+2;i++)
    {
        j=((i%4)+4)%4;
        int tx, ty;
        tx=x+dir[j][0];
        ty=y+dir[j][1];
        if(tx>=0&&tx<n&&ty>=0&&ty<m&&map[tx][ty]!='#')
        {
            return 1+dfs_left(tx, ty, j);
        }
    }
}
int dfs_right(int x, int y, int p)
{
    int i, j;
    if(map[x][y]=='E') return 1;
    for(i=p+1;i>=p-2;i--)
    {
        j=((i%4)+4)%4;
        int tx, ty;
        tx=x+dir[j][0];
        ty=y+dir[j][1];
        if(tx>=0&&tx<n&&ty>=0&&ty<m&&map[tx][ty]!='#')
        {
            return 1+dfs_right(tx, ty, j);
        }
    }
}
void bfs_min()
{
    int i, j, k;
    memset(mark, 0, sizeof(mark));
    queue<node>q;
    while(!q.empty()) q.pop();
    e.x=px, e.y=py, e.step=1;
    q.push(e);
    while(!q.empty())
    {
        e=q.front();
        q.pop();
        if(e.x==ex&&e.y==ey) break;
        for(i=0;i<4;i++)
        {
            s.x=e.x+dir[i][0];
            s.y=e.y+dir[i][1];
            s.step=e.step+1;
            if(s.x<0||s.x>=n||s.y<0||s.y>=m||map[s.x][s.y]=='#'||mark[s.x][s.y])
                continue;
            q.push(s);
            mark[s.x][s.y]=1;
        }
    }
    min_step=e.step;
}
int main()
{
    int i, j, k;
    while(scanf("%d", &t)!=EOF)
    {
        while(t--)
        {
            scanf("%d%d", &m, &n);
            for(i=0;i<n;i++)
            scanf("%s", &map[i]);
            for(i=0;i<n;i++)
                for(j=0;j<m;j++)
                {
                    if(map[i][j]=='S') {px=i;py=j;}
                    else if(map[i][j]=='E') {ex=i;ey=j;}
                }
            start();
            left_step=dfs_left(px, py, pp);
            right_step=dfs_right(px, py, pp);
            bfs_min();
            printf("%d %d %d\n", left_step, right_step, min_step);
        }
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/tim11/archive/2012/08/18/2645379.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值