Fire!
原题链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=2671&mosmsg=Submission+received+with+ID+18577889
题意:一个迷宫中有多处地方起火,问,人能不能在火烧到之前走出迷宫,如果能,则输出最短的时间思路:我们可以把起火的位置和人的位置存起来,然后一一压入队列中(要最后存入人的位置,这样才能够判断人下一步能不能走),另外就是在外围在加上一圈点,这样以便与判断人走出迷宫。
注意:火和人的下一步的判断标准不同,所以设了两个标记变量。
ps:比较坑的是一开始没看清题,没看出是多个地点着火,最后在UVA的Udebug中给的样例中才发现。。。0.0多读题
代码:
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
int x,y,step,ic;//ic记录身份
} w[1000];
int vis[1010][1010];//记录火烧过的
int vix[1010][1010];//记录人走过的
char s[1010][1010];
int go[4][2]= {0,1,0,-1,1,0,-1,0};
int n,m;
int bfs(int sum)
{
memset(vix,0,sizeof(vix));
memset(vis,0,sizeof(vis));
queue<node>q;
node a,b;
for(int i=0;i<sum;i++)//火的位置入队
{
q.push(w[i]);
vis[w[i].x][w[i].y]=1;
}
q.push(w[sum]);//人的位置入队
vix[w[sum].x][w[sum].y]=1;
while(!q.empty())
{
a=q.front();
if(a.ic==0)
{
if(a.x<=0||a.x>n||a.y<=0||a.y>m)
return a.step;
}
for(int i=0; i<4; i++)
{
b.x=a.x+go[i][0];
b.y=a.y+go[i][1];
b.step=a.step+1;
b.ic=a.ic;
if(b.ic==0)
{
if(!vix[b.x][b.y]&&s[b.x][b.y]=='.'&&!vis[b.x][b.y])
{
vix[b.x][b.y]=1;
q.push(b);
}
}
else if(b.ic==1)
{
if(!vis[b.x][b.y]&&s[b.x][b.y]=='.'&&b.x>0&&b.x<=n&&b.y>0&&b.y<=m)
{
vis[b.x][b.y]=1;
q.push(b);
}
}
}
q.pop();
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int i,j,x,y,sum=0;
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++)
{
scanf("%s",s[i]+1);
for(j=1; j<=m; j++)
{
if(s[i][j]=='F')
w[sum].x=i,w[sum].y=j,w[sum].step=0,w[sum].ic=1,sum++;//火的身份是1
else if(s[i][j]=='J')
x=i,y=j;
}
}
w[sum].x=x,w[sum].y=y,w[sum].step=0,w[sum].ic=0;//人的身份是0
for(i=0;i<=n+1;i++)//在外围加一圈
s[i][0]='.',s[i][m+1]='.';
for(j=0;j<=m+1;j++)
s[0][j]='.',s[n+1][j]='.';
int ans=bfs(sum);
if(ans==-1)
printf("IMPOSSIBLE\n");
else
printf("%d\n",ans);
}
return 0;
}