BFS hdu-4528 小明系列故事——捉迷藏

来源:互联网 发布:融华财富网络贷款 编辑:程序博客网 时间:2024/05/19 03:29

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4528

题目意思:

给你一个矩阵,'.‘ 表示能通过,’X' 表示不能通过,告诉你S、D、E 的位置。

问你从S出发在规定的时间内,能否同时找到D和E。只要两个人之间没有障碍,就能找到。

解题思路:

BFS,注意记录访问过的节点的时候,要注意状态的确定。

vis[x][y][i][j]是否访问坐标为x,y,且看到D和E的状态。i=0表示没看到D,i=1表示看到了D,j=0表示没看到E,j=1表示看到了E。

贴出一组测试数据:

7 7 19

S。。。。。。

。X。。。。。

。。X。。。。

。。。X。。。

。。。。X。。

。。。。。XD

。。。。。。E

答案为:18


代码:

#include<iostream>#include<cmath>#include<cstdio>#include<cstdlib>#include<string>#include<cstring>#include<algorithm>#include<vector>#include<map>#include<stack>#include<list>#include<queue>#define eps 1e-6#define INF (1<<30)#define PI acos(-1.0)using namespace std;char save[120][120];bool se[2][120][120],vis[120][120][2][2];struct Po{   int x,y,t;   bool flag1,flag2;}s,d,e;int dir[4][2]={0,-1,1,0,0,1,-1,0};int n,m,t;bool check(int x,int y){   if(x<1||x>n||y<1||y>m)      return false;   return true;}void init(int x,int y,int num){   for(int i=0;i<4;i++)   {      int xx=x,yy=y;      while(true)  //预处理能找到D和E的位置      {         xx+=dir[i][0],yy+=dir[i][1];         if(check(xx,yy)==false||save[xx][yy]=='X')            break;         if(num==0&&save[xx][yy]=='E') //注意开始S的位置,应该把它当做.            break;         if(num==1&&save[xx][yy]=='D')            break;         se[num][xx][yy]=true;      }   }   return ;}bool flag;int bfs(){   queue<struct Po>myq;   s.t=0;   myq.push(s);   while(!myq.empty())   {      struct Po cur=myq.front();      myq.pop();      for(int i=0;i<4;i++)      {         int xx=cur.x+dir[i][0],yy=cur.y+dir[i][1],tt=cur.t+1;         if(tt>t)            break;         if(check(xx,yy)==false||save[xx][yy]!='.')            continue;         struct Po temp;         if(se[0][xx][yy]||cur.flag1) //如果前面已找到了D,或者当前恰好找到了D            temp.flag1=true;         else            temp.flag1=false;         if(se[1][xx][yy]||cur.flag2)            temp.flag2=true;         else            temp.flag2=false;         if(temp.flag1&&temp.flag2)         {            flag=true;            return tt;         }         if(vis[xx][yy][temp.flag1][temp.flag2]) //状态前面已经找了            continue;         temp.x=xx,temp.y=yy,temp.t=tt;         vis[xx][yy][temp.flag1][temp.flag2]=true;         myq.push(temp);      }   }   return -1;}int main(){   int tt;   scanf("%d",&tt);   for(int ca=1;ca<=tt;ca++)   {      scanf("%d%d%d",&n,&m,&t);      for(int i=1;i<=n;i++)      {         scanf("%s",save[i]+1);         for(int j=1;j<=m;j++)         {            if(save[i][j]=='S')               s.x=i,s.y=j;            if(save[i][j]=='D')               d.x=i,d.y=j;            if(save[i][j]=='E')               e.x=i,e.y=j;         }      }     // printf("s:%d %d  e:%d %d  d:%d %d\n",s.x,s.y,e.x,e.y,d.x,d.y);      memset(se,false,sizeof(se));      init(d.x,d.y,0); //预处理能够看见的D的坐标      init(e.x,e.y,1); //预处理能够看见的E的坐标      flag=false;      if(se[0][s.x][s.y])         s.flag1=true;      else         s.flag1=false;      if(se[1][s.x][s.y])         s.flag2=true;      else         s.flag2=false;      printf("Case %d:\n",ca);      if(s.flag1&&s.flag2)      {         printf("0\n");         continue;      }      memset(vis,false,sizeof(vis));      vis[s.x][s.y][s.flag1][s.flag2]=true;      int ans=bfs();      if(flag==false)         printf("-1\n");      else         printf("%d\n",ans);   }   return 0;}


原创粉丝点击