HDU1728:逃离迷宫

传送门

题意

给出一个只由'.'与''构成的nm的图,在不多于k次转弯,问是否能让起点到达终点

分析

这道题花了我2h+,一开始写了一个优先队列+BFS+is数组标记,发现有一组数据过不了

2
3 3
..*
...
*.*
1 1 1 3 2

又用队列重写,发现还是过不了,于是看了这篇blog,扫的时候要将同方向直到*的所有未访问点都放入队列,感谢qqspeed
这种有转弯数限制的题目有些难,它不能用优先队列,因为相同转弯数的点相同位置方向不同就有不同的结果,而用队列也要注意读取点的顺序,比较巧妙

trick

1.开始点与终点可重合,QAQ
2.注意点放入队列的顺序

代码

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define R(i,a,b) for(int i=a;i<b;++i)
#define F(i,a,b) for(int i=a;i<=b;++i)
#define mem(a,b) memset(a,b,sizeof(a))
int t,n,m,k,a[111][111],sx,sy,ex,ey;
int dir[4][2]={0,1,0,-1,-1,0,1,0};
int flag;
bool vis[111][111];
char s[111];
struct node
{
    int x,y,turn;
}tmp,p;
bool check(int x,int y)
{
    if(x<1||y<1||x>n||y>m||a[x][y]==0) return 0;return 1;
}
queue<node>pq;
void bfs()
{
    //printf("1.x=%d y=%d cnt=%d pre=%d\n",x,y,cnt,pre);
    //if(cnt==k&&(x-x2)&&(y-y2)) return ;
    //printf("(cnt==2&&(x-x2)&&(y-y2))=%d\n",(cnt==2&&(x-x2)&&(y-y2)));
    //if(cnt==2&&(x-x2)&&(y-y2)) return ;
    //if(x2==x&&y2==y) { flag=1;return ; }
    //printf("a[%d][%d]=%d\n",x,y,a[x][y]);
    //printf("2.x=%d y=%d cnt=%d pre=%d\n",x,y,cnt,pre);
    while(!pq.empty()) pq.pop();
    tmp={sx,sy,-1};pq.push(tmp);
    vis[sx][sy]=1;
    while(!pq.empty())
    {
        tmp=pq.front();pq.pop();
        if(tmp.x==ex&&tmp.y==ey&&tmp.turn<=k) { flag=1;return ; }
        p.turn=tmp.turn+1;
        R(i,0,4)
        {
        int xx=tmp.x+dir[i][0],yy=tmp.y+dir[i][1];

        while(check(xx,yy))
        {
            if(!vis[xx][yy])
            {
            vis[xx][yy]=1;
            //printf("3.a[%d][%d]=%d turn=%d i=%d\n",xx,yy,a[xx][yy],cnt1,i);
            p.x=xx,p.y=yy;
            pq.push(p);
            }
            xx+=dir[i][0],yy+=dir[i][1];
        }

        }
     //   printf("3.x=%d y=%d cnt=%d pre=%d\n",xx,yy,cnt,pre);
        //if(pre!=i) dfs(xx,yy,cnt+1,i);else dfs(xx,yy,cnt,i);
    }
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d %d",&n,&m);
        F(i,1,n)
        {
            scanf("%s",s);
            for(int j=0;s[j]!='\0';++j)
            {
                if(s[j]=='.') a[i][j+1]=1;
                else a[i][j+1]=0;
            }
        }
            scanf("%d %d %d %d %d",&k,&sy,&sx,&ey,&ex);
            if(a[sx][sy]!=a[ex][ey]) { flag=0;goto L; }
            flag=0;mem(vis,0);
            bfs();
            L:if(flag) puts("yes");else puts("no");
    }
    return 0;
}
posted @ 2017-04-06 23:32  遗风忘语  阅读(453)  评论(0编辑  收藏  举报