Hdu 1728 逃离迷宫(BFS)

Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1728

 

这题不是用步数限制行走,而是用拐弯数限制行走

参考了这篇文章:http://972169909-qq-com.iteye.com/blog/1244218

如果你的代码是优先向右搜索就会出错
红色的线是先搜的,由于最多转一次弯,所以不合题意;
蓝色是后搜的,因为遇到转弯数相等所以不往下走了了,但是继续走是可以满足题意输出"yes"的

 

 

所以很明显每一步要走就要确定方向一直走到底。用一个数组保存走到每个地方所用的拐弯数。如果走到这步时的拐弯数小于记录在数组的拐弯数,则更新数组,并将这一步放入队列。最后判断能否走到时,可以看走到终点时所用最小拐弯数是否小于等于题目所要求的最大拐弯数。

 

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

typedef struct node{
    int x,y;  //坐标
    int lastDir;//上次的拐弯方向
    int bouts;//拐弯数
    friend bool operator < (node t1, node t2)
    {
        return t2.bouts < t1.bouts;
    }
}node;

const int maxn = 110;
const int INF = 65523655;
int m,n;
int k,c1,r1,c2,r2; //题目中的x1代表列,此处用c1代表列,r1代表行
char map[maxn][maxn];
int step[maxn][maxn];//存每个点的最小拐弯数
int dir[4][2]={ -1,0, 1,0, 0,-1, 0,1 }; // u / d / l / r

void input()
{
    int i,j;
    memset(map,0,sizeof(map));
    for(i=0;i<m;i++)
    {
        getchar();
        for(j=0;j<n;j++)
            scanf("%c",&map[i][j]);
    }
    cin>>k>>c1>>r1>>c2>>r2;
}

void bfs()
{
    int i,j;
    for(i=0;i<m;i++)
        for(j=0;j<n;j++)
            step[i][j]=INF; //初始化
    priority_queue <node> qe;
    node t, next;
    t.x=r1-1;
    t.y=c1-1;
    step[t.x][t.y]=0;
    
    //第一步
    for(i=0;i<4;i++)
    {
        next.x=t.x+dir[i][0];
        next.y=t.y+dir[i][1];
        next.lastDir=i;
        next.bouts=0;
        while( map[next.x][next.y]!='*' && next.x>=0 && next.x<m && next.y>=0 && next.y<n )
        {
            if( step[next.x][next.y] > next.bouts )
            {
                step[next.x][next.y] = next.bouts;
                qe.push(next);
            }
            next.x=next.x+dir[i][0];//一个方向走到底,知道不能走
            next.y=next.y+dir[i][1];
        }
    }
    
    while( !qe.empty() )
    {
        t=qe.top();
        qe.pop();

        for(i=0;i<4;i++)
        {
            next.x=t.x+dir[i][0];
            next.y=t.y+dir[i][1];
            next.bouts=t.bouts;
            if(t.lastDir!=i)  //判断拐弯数是否加1
                next.bouts++;
            next.lastDir=i;
            while( map[next.x][next.y]!='*' && next.x>=0 && next.x<m && next.y>=0 && next.y<n &&next.bouts<=k)
            {
                if( step[next.x][next.y] > next.bouts ) //是否更新数组
                {
                    step[next.x][next.y] = next.bouts;
                    qe.push(next);//因为更新了数组,有必要加入队列
                }
                next.x=next.x+dir[i][0]; //一个方向走到底,知道不能走
                next.y=next.y+dir[i][1];
            }
        }

    }
    return ;
}

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>m>>n;
        input();
        if(r1==r2 && c1==c2) //起点与终点相同,直接输出yes
            {
                cout<<"yes\n";
                continue;
            }
        bfs();
        if(step[r2-1][c2-1]<=k)
            cout<<"yes"<<endl;
        else
            cout<<"no"<<endl;
    }
    return 0;
}

 

posted @ 2014-09-06 22:54  Emerald  阅读(542)  评论(0编辑  收藏  举报