nyoj 999 师傅又被妖怪抓走了
师傅又被妖怪抓走了
时间限制: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; }