HDU 1728 逃离迷宫 (搜索)

来源:互联网 发布:python适合初学者的书 编辑:程序博客网 时间:2024/05/21 23:32

逃离迷宫

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 19550    Accepted Submission(s): 4747


Problem Description
  给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?
 

Input
  第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,
  第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。
 

Output
  每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
 

Sample Input
25 5...***.**...........*....1 1 1 1 35 5...***.**...........*....2 1 1 1 3
 

Sample Output
noyes

         这题类似于Hdu1175,都存在一个最大的转弯次数上限。题目要求在达到转向次数上限前到达目的点,也就是求起始点到目的点的最少转向次数。

         如果用行走步数来BFS,那么当存在多条起点至终点的最短路径时,会依据第一次搜索的结果做判定,也就是说在搜索正确路径前,如果先搜索了转弯数较多的最短路径,则会判定为错误,若重复搜索,则会极大地消耗内存,导致内存超限。所以将搜索最短路改为搜索转向次数最少的路径。也就是先搜索不转向可到达的点,再搜索一次转向可到达的点。以此类推。当搜索到目的点时,必定是转弯次数最小的路径。

          如果使用DFS来写,则需要添加一个记忆数组来剪枝。如果在以前的搜索中曾访问过该点,则判断目前已转向次数是否大于或等于曾记录的值,若是,则不可能在在要求范围内到达终点,剪枝。


BFS代码:

#include<iostream>#include<string.h>#include<queue>#include<malloc.h>using namespace std;typedef struct P{    int x,y;    int counts;} P;char a[105][105];int vis[105][105];const int dx[]= {1,0,-1,0};const int dy[]= {0,1,0,-1};int x1,y1,x2,y2,n,m,k;int judge(int x ,int y){    if(x>=1&&x<=n&&y>=1&&y<=m&&a[x][y]!='*')        return 1;    return 0;}int bfs(){    int i,nx,ny;    queue<P>que;    P p,tp;    p.x = x1;    p.y = y1;    p.counts =-1;    que.push(p);    while(!que.empty())    {        p = que.front();        que.pop();        if(p.counts>k)                  //如果出现转弯次数大于K,则代表无法在次数限制内到达终点            return 0;        tp = p;        tp.counts = p.counts+1;         //从队列中取出后,一定会发生转向        for(i=0; i<4; i++)        {            nx = p.x + dx[i];            ny = p.y + dy[i];            while(judge(nx,ny))       //不发生转向,沿同一方向一直访问至尽头            {                if(vis[nx][ny]==0)     //当该地址未被访问才进入队列                {                    tp.x = nx;                    tp.y = ny;                    que.push(tp);                    vis[nx][ny]=1;                }                if(nx==x2&&ny==y2)                {                    if(tp.counts<=k)                        return 1;                    else                        return 0;                }                nx = nx + dx[i];                ny = ny + dy[i];            }        }    }    return 0;}int main(){    int t,i,j;    cin>>t;    while(t--)    {        cin>>n>>m;        for(i=1; i<=n; i++)            for(j=1; j<=m; j++)            {                cin>>a[i][j];                vis[i][j]=0;            }        cin>>k>>y1>>x1>>y2>>x2;        vis[x1][y1]=1;        if(bfs())            cout<<"yes"<<endl;        else            cout<<"no"<<endl;    }}

DFS代码:

#include<iostream>#include<string.h>using namespace std;char a[105][105];int vis[105][105];int cmp[105][105];const int dx[]={1,0,-1,0};const int dy[]={0,1,0,-1};int x1,y1,x2,y2,n,m,k,flag;int judge(int x,int y){    if(x>=1&&x<=n&&y>=1&&y<=m&&a[x][y]=='.'&&vis[x][y]==0)        return 1;    return 0;}void dfs(int x,int y,int turn,int counts){    int i,nx,ny,tempturn,tempcounts;    if(flag||counts>k||(counts==k&&(x!=x2&&y!=y2)))        return;    if(x==x2&&y==y2)    {        if(counts<=k)        flag = 1;        return;    }    tempturn=turn;    tempcounts = counts;    for(i=0;i<4;i++)    {        nx=x+dx[i];        ny=y+dy[i];        if(judge(nx,ny))        {            if(cmp[nx][ny]==0||cmp[nx][ny]>counts)                cmp[nx][ny]=counts;            else if(cmp[nx][ny]<counts)                continue;           if(turn!=i&&turn!=-1)            counts++;            vis[nx][ny]=1;            turn = i;            dfs(nx,ny,turn,counts);            vis[nx][ny]=0;            turn = tempturn;            counts = tempcounts;        }    }}int main(){    int t;    cin>>t;    while(t--)    {        cin>>n>>m;        for(int i=1;i<=n;i++)            for(int j=1;j<=m;j++)        {            cin>>a[i][j];            vis[i][j]=0;            cmp[i][j]=0;        }        flag = 0;        cin>>k>>y1>>x1>>y2>>x2;        vis[x1][y1]=1;        dfs(x1,y1,-1,0);        if(flag)            cout<<"yes"<<endl;        else            cout<<"no"<<endl;    }}

以上

0 0
原创粉丝点击