您的位置:首页 > 其它

nyoj999 师傅又被妖怪抓走了 (预处理+bfs+状态压缩)

2016-03-26 12:22 555 查看
题目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

这道题让我很焦灼啊。。。开个玩笑 哈哈

这道题的发现定义为可以直接看到对方,所以是不能走X D E 只能是看到

所以在录入数据的时候 我们就提前做好预处理。把D E的四个方向 能看到的地方都处理一下

然后就是bfs了 而在这里 我提交了几次 发现都不对 后来无意中的一个数据启发了我

2 3 1

.S.

DXE

输出-1

2 3 3

.S.

DXE

输出3

聪明的你 看出来了吗?如果我们用通常的vis数组标记走过的路径

,对于第二条测试数据 只会输出-1  因为它不会走回头路 。我又存在侥幸的心理 不用vis数组标记了 发现 果然TLE

 然后就是不做了 走在路上还在想 究竟在这里该怎么优化 。。。果然 睡觉的时候被我想到了 今天早上一大早 就起来做了。

具体方法是 如果又定义了两个数组visE【x】【y】 visD【x】【y】分别记录在x,y点 是否已经找到过E 或D  。当某个点已经遍历过

我们再判断当前的visD 和visE和之前的是否一致  如果一致 我们就不用走 如果不一致 证明我们在其它点找到了D或E  现在要回来。

具体看代码把

#include <stdio.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int n,m;
int t;
int s1,s2;
int d1,d2;
int e1,e2;
int dir[4][2]={1,0,0,1,-1,0,0,-1};
char map[105][105];
bool visD[105][105];
bool visE[105][105];
bool vis[105][105];
struct node
{
int x,y;
int step;
bool isfindD;
bool isfindE;
friend bool operator<(node a,node b)
{
return a.step>b.step;
}
};
void prepare(int x,int y,char ch)
{
char ch2;
int x2,y2;
if(ch=='D')
ch2='E',x2=e1,y2=e2;
else
ch2='D',x2=d1,y2=d2;
for(int i=x-1;i>=0;i--)
{
if(map[i][y]=='X'||i==x2&&y==y2)
break;
if(map[i][y]=='.')
map[i][y]=ch;
else if(map[i][y]==ch2)
map[i][y]='*';
else if(map[i][y]=='S')
{
map[i][y]=ch;
break;
}
}
for(int i=x+1;i<n;i++)
{
if(map[i][y]=='X'||i==x2&&y==y2)
break;
if(map[i][y]=='.')
map[i][y]=ch;
else if(map[i][y]==ch2)
map[i][y]='*';
else if(map[i][y]=='S')
{
map[i][y]=ch;
break;
}
}
for(int i=y+1;i<m;i++)
{
if(map[x][i]=='X'||x==x2&&i==y2)
break;
if(map[x][i]=='.')
map[x][i]=ch;
else if(map[x][i]==ch2)
map[x][i]='*';
else if(map[x][i]=='S')
{
map[x][i]=ch;
break;
}
}
for(int i=y-1;i>=0;i--)
{
if(map[x][i]=='X'||x==x2&&i==y2)
break;
if(map[x][i]=='.')
map[x][i]=ch;
else if(map[x][i]==ch2)
map[x][i]='*';
else if(map[x][i]=='S')
{
map[x][i]=ch;
break;
}
}
}
bool limit(int x,int y)
{
if(x==d1&&y==d2)
return false;
if(x==e1&&y==e2)
return false;
if(x<0||y<0||x>=n||y>=m||map[x][y]=='X')
return false;
return true;
}
void check_result(node &temp1)
{
int x=temp1.x;
int y=temp1.y;
if(map[x][y]=='D')
temp1.isfindD=true;
else if(map[x][y]=='E')
temp1.isfindE=true;
else if(map[x][y]=='*')
temp1.isfindD=temp1.isfindE=true;
}
int bfs(int x1,int y1,int time)
{
node temp1,temp2;
priority_queue<node>s;
while(!s.empty())
s.pop();
temp1.x=x1;temp1.y=y1;temp1.step=0;
temp1.isfindD=temp1.isfindE=false;
check_result(temp1);
visE[x1][y1]=temp1.isfindE;
visD[x1][y1]=temp1.isfindD;
vis[x1][y1]=true;
s.push(temp1);
while(!s.empty())
{
temp1=temp2=s.top();
s.pop();
if(temp1.step>time)
return -1;
if(temp1.isfindD&&temp1.isfindE)
return temp1.step;
for(int i=0;i<4;i++)
{
int x1=temp1.x+dir[i][0];
int y1=temp1.y+dir[i][1];
if(limit(x1,y1)&&(!vis[x1][y1]||!(visE[x1][y1]==temp1.isfindE&&visD[x1][y1]==temp1.isfindD)))
{
temp1.x=x1;
temp1.y=y1;
temp1.step++;
check_result(temp1);
vis[x1][y1]=true;
visE[x1][y1]=temp1.isfindE;
visD[x1][y1]=temp1.isfindD;
s.push(temp1);
temp1=temp2;
}
}
}
return -1;
}
int main()
{
int ncase=1;
while(~scanf("%d %d %d",&n,&m,&t))
{
memset(map,0,sizeof(map));
for(int i=0;i<n;i++)
{
getchar();
for(int j=0;j<m;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='S')
{
s1=i;
s2=j;
}
if(map[i][j]=='D')
{
d1=i;
d2=j;
}
if(map[i][j]=='E')
{
e1=i;
e2=j;
}
}
}
prepare(d1,d2,'D');
prepare(e1,e2,'E');
memset(visD,false,sizeof(visD));
memset(visE,false,sizeof(visE));
memset(vis,false,sizeof(vis));
printf("Case %d:\n%d\n",ncase++,bfs(s1,s2,t));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: