ccf模拟题。
I’m stuck!
时间限制: | 1.0s |
内存限制: | 256.0MB |
问题描述
给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七个字符中的一个,分别表示如下意思:
'#': 任何时候玩家都不能移动到此方格;
'+': 当玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
'-': 当玩家到达这一方格后,下一步可以向左右两个方向相邻的一个非'#'方格移动一格;
'|': 当玩家到达这一方格后,下一步可以向上下两个方向相邻的一个非'#'方格移动一格;
'.': 当玩家到达这一方格后,下一步只能向下移动一格。如果下面相邻的方格为'#',则玩家不能再移动;
'S': 玩家的初始位置,地图中只会有一个初始位置。玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
'T': 玩家的目标位置,地图中只会有一个目标位置。玩家到达这一方格后,可以选择完成任务,也可以选择不完成任务继续移动。如果继续移动下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格。
此外,玩家不能移动出地图。
请找出满足下面两个性质的方格个数:
1. 玩家可以从初始位置移动到此方格;
2. 玩家不可以从此方格移动到目标位置。
输入格式
输入的第一行包括两个整数R 和C,分别表示地图的行和列数。(1 ≤ R, C ≤ 50)。
接下来的R行每行都包含C个字符。它们表示地图的格子。地图上恰好有一个'S'和一个'T'。
输出格式
如果玩家在初始位置就已经不能到达终点了,就输出“I'm stuck!”(不含双引号)。否则的话,输出满足性质的方格的个数。
样例输入
5 5
--+-+
..|#.
..|##
S-+-T
####.
样例输出
2
样例说明
如果把满足性质的方格在地图上用'X'标记出来的话,地图如下所示:
--+-+
..|#X
..|##
S-+-T
#include<bits/stdc++.h>
int xx[5]={1,-1,0,0};
int yy[5]={0,0,1,-1};
int vis[51][51];
int can[51][51];
char a[51][51];
int r,c;
int flag;
int counter;
void bfs(int x,int y)
{
int dx,dy,rear,front;
rear=front=0;
while(front<=rear)
{
if(a[x][y]=='+'||a[x][y]=='S'||a[x][y]=='T')
{
for(int i=0;i<4;i++)
{
dx=x+xx[i];
dy=y+yy[i];
if(dx>=0&&dx<r&&dy>=0&&dy<c&&a[dx][dy]!='#'&&vis[dx][dy]!=1)
{
vis[dx][dy]=1;
if(flag==0&&a[dx][dy]=='T')
counter++;
if(flag)
can[dx][dy]=1;
bfs(dx,dy);
rear++;
}
}
}
else if(a[x][y]=='-')
{
for(int i=2;i<4;i++)
{
dx=x+xx[i];
dy=y+yy[i];
if(dx>=0&&dx<r&&dy>=0&&dy<c&&a[dx][dy]!='#'&&vis[dx][dy]!=1)
{ if(flag)
can[dx][dy]=1;
if(flag==0&&a[dx][dy]=='T')
counter++;
vis[dx][dy]=1;
bfs(dx,dy);
rear++;
}
}
}
else if(a[x][y]=='|')
{
for(int i=0;i<2;i++)
{
dx=x+xx[i];
dy=y+yy[i];
if(dx>=0&&dx<r&&dy>=0&&dy<c&&a[dx][dy]!='#'&&vis[dx][dy]!=1)
{ vis[dx][dy]=1;
if(flag)
can[dx][dy]=1;
if(flag==0&&a[dx][dy]=='T')
counter++;
bfs(dx,dy);
rear++;
}
}
}
else if(a[x][y]=='.')
{
dx=x+xx[0];
dy=y+yy[0];
if(dx>=0&&dx<r&&dy>=0&&dy<c&&a[dx][dy]!='#'&&vis[dx][dy]!=1)
{ if(flag)
can[dx][dy]=1;
if(flag==0&&a[dx][dy]=='T')
counter++;
vis[dx][dy]=1;
bfs(dx,dy);
rear++;
}
}
front++;
}
return;
}
int main()
{
int x_e,x_s,k1=51,k2=51;
scanf("%d %d",&r,&c);
memset(vis,0,sizeof(vis));
memset(can,0,sizeof(can));
for(int i=0;i<r;i++)
{
scanf("%s",&a[i]);
}
flag=1;
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
{
if(a[i][j]=='S')
{
vis[i][j]=1;
bfs(i,j);
}
}
}
flag=0;
int ans=0;
bfs(0,2);
for(int i=0;i<r;i++)
{
for(int j=0;j<c;j++)
{
if(can[i][j]==1&&a[i][j]!='T'&&a[i][j]!='S')
{ memset(vis,0,sizeof(vis));
ans++;
bfs(i,j);
}
if(a[i][j]=='T')
{
k1=i;
k2=j;
}
}
}
if(can[k1][k2]==1)
printf("%d",ans-counter);
else
printf("I'm stuck!");
}
####X
一开始少了一个vis[dx][dy]=1;30分后来改过来了90分然后才发现我没判断I’m stuck!的条件所幸很简单我又加上了。我觉得我的代码比网上大多数都好理解吧。虽然有点长。
说一下思路吧,一开始时判断能从S到达的点,并把这些点做标记。就是can数组。后来在从被标记的点出发,看他能不能到T点,能的话counter加一。最后再用标记的点个数的总数减去那些能到T的点。i'm stuck的条件也很好判断,当我再给那些点做标记的时候如果T点没标记的话证明从s出发不能到T;