nyoj 999 师傅又被妖怪抓走了

师傅又被妖怪抓走了

时间限制:1000 ms  |  内存限制:65535 KB

难度:3

描述

话说唐僧复得了孙行者,师徒们一心同体,共诣西方。自宝象国救了公主,承君臣送出城西,沿路饥餐渴饮,悟空便为师傅去化斋,等悟空回来,悟净慌慌张张的对悟空说:“不好了,不好了”,还没等悟净说完,悟空说:“师傅又被妖怪抓走了”,悟净:“NO” ,悟空一脸茫然,悟净:“师傅和二师兄都被妖怪抓走了”。悟空(晕!)。为了防止悟空救人,妖怪先把唐憎和八戒分别藏起来,如果悟空在T分钟之后还没找到人,那必定是被妖怪吃掉了。假设悟空在一个nm列的矩阵内,悟空在每一分钟可以走到上,下,左,右的其中的一个可以走的位置,每次只能走一步。我们把发现定义为可以直接看到对方,也就是说两个人在同一行或者同一列,并且中间没有障碍物或者没有其他人就可以看到对方。

输入

有多组测试数据,每组首先是三个正整数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:
",tcase++);
		if(ans<=t)
			printf("%d
",ans);
		else
			puts("-1");
	}
	return 0;
}        

  

原文地址:https://www.cnblogs.com/zhangliu/p/7053036.html