题目链接:
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;
}