师傅又被妖怪抓走了
时间限制:1000 ms | 内存限制:65535 KB
难度:3
描述
话说唐僧复得了孙行者,师徒们一心同体,共诣西方。自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟空便为师傅去化斋,等悟空回来,悟净慌慌张张的对悟空说:“不好了,不好了”,还没等悟净说完,悟空说:“师傅又被妖怪抓走了”,悟净:“NO!” ,悟空一脸茫然,悟净:“师傅和二师兄都被妖怪抓走了”。悟空(晕!)。为了防止悟空救人,妖怪先把唐憎和八戒分别藏起来,如果悟空在T分钟之后还没找到人,那必定是被妖怪吃掉了。假设悟空在一个n行m列的矩阵内,悟空在每一分钟可以走到上,下,左,右的其中的一个可以走的位置,每次只能走一步。我们把发现定义为可以直接看到对方,也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方。
输入
有多组测试数据,每组首先是三个正整数n , m (3<=n,m<=100), T,(0<=T<=100) 分别代表行数,列数,规定的时间。接下来n 行,每行 m 个字符。其中’ S ’ 代表悟空的位置,’ D ’代表师傅位置,’ E ’代表八戒的位置。并且保证都只有一个. ’ X ’代表墙 ,’ . ’代表空地 .
输出
每组先输出一行Case c:(c表示当前的组数,从1开始计数);
接下来一行,如果悟空可以在规定时间内找到两人,则输出最少需要的时间,否则输出-1。
样例输入
5 6 3
XXD...
....E.
....X.
....S.
......
5 6 3
XDX...
....E.
......
....S.
......
5 6 8
XXDX..
.XEX..
......
....S.
......
样例输出
Case 1:
-1
Case 2:
3
Case 3:
-1
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
int dir[4][2]={-1,0,1,0,0,-1,0,1};
int visit[105][105][4];
char map[105][105];
int n,m,t,ans;
struct Node{
int x,y;
int step,st;
};
//状态压缩,将D点和E点所在的行列的‘.’扩展为d和e,
// 把师傅所在行和列标记为 1 状态 'd'
// 二师兄所在行和列标记为 2 状态 'e'
// 如果师傅和二师兄在同一行或同一列,重合的部分标记为3状态 'x'
// 要想把师傅和二师兄都找到:
// 要么先找到师傅,再找到二师兄;
// 要么先找到二师兄,再找到师傅;
// 要么同时找到
int ST_solve(char x,int st)//处理当前所走的状态
{
if(x=='d')
st|=1;
else if(x=='e')
st|=2;
else if(x=='y')
st|=3;
return st;
}
bool check(int x,int y) //判断是否能走,可以把师傅或二师兄看做墙不能走
{
if(map[x][y]=='X' || map[x][y]=='D' || map[x][y]=='E')
return false;
return true;
}
char solve(char x,int ok) //师傅或二师兄所在行和列标记 有多不同
{
if(ok&&x=='e' || !ok&&x=='d')
return 'y'; //'y' 可以记为把师傅和二师兄都被找到的状态
return ok?'d':'e';
}
//状态压缩
void Isit(int x,int y,int ok)//处理师傅或二师兄所在的行和列
{
for(int i=x-1;i>=0&&check(i,y);i--)
map[i][y]=solve(map[i][y],ok);
for(int i=x+1;i<m&&check(i,y);i++)
map[i][y]=solve(map[i][y],ok);
for(int j=y-1;j>=0&&check(x,j);j--)
map[x][j]=solve(map[x][j],ok);
for(int j=y+1;j<n&&check(x,j);j++)
map[x][j]=solve(map[x][j],ok);
}
void bfs(Node s)
{
queue<Node>q;
memset(visit,0,sizeof(visit));
s.step=0;
s.st=ST_solve(map[s.x][s.y],0);
q.push(s);
visit[s.x][s.y][s.st]=1;
while(!q.empty())
{
Node a,b;
a=q.front();
q.pop();
if(a.st==3)//问是否能达到3的状态,即师傅和二师兄都被找到
{
ans=a.step;
return;
}
for(int i=0;i<4;i++)
{
b.x=a.x+dir[i][0];
b.y=a.y+dir[i][1];
b.step=a.step+1;
b.st=a.st;
//if(b.x>=0&&b.x<n&&b.y>=0&&b.y<m&&!visit[b.x][b.y][b.st]&&map[b.x][b.y]=='.') (错误)
if(b.x>=0&&b.x<n&&b.y>=0&&b.y<m&&!visit[b.x][b.y][b.st]&&check(b.x,b.y))
{
b.st=ST_solve(map[b.x][b.y],b.st);
visit[b.x][b.y][b.st]=1;
q.push(b);
}
}
}
}
int main()
{
int tcase=1;
while(~scanf("%d%d%d",&n,&m,&t))
{
Node s;
for(int i=0;i<n;i++)
{
scanf("%s",&map[i]);
for(int j=0;j<m;j++)
{
if(map[i][j]=='S')
{
s.x=i;
s.y=j;
}
}
}
for(int i=0;i<n;i++) //预处理
{
for(int j=0;j<m;j++)
{
if(map[i][j]=='D')
Isit(i,j,1);
else if(map[i][j]=='E')
Isit(i,j,0);
}
}
ans=10005;
bfs(s);
printf("Case %d:\n",tcase++);
if(ans<=t)
printf("%d\n",ans);
else
puts("-1");
}
return 0;
}