题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=82
题目解析:本题主要注意对门的处理,如果当前门的所有钥匙都找到了,那么这个门就可以当做点,否则的话,加入队列,但不进行标记,意思就是说可以多次访问,直到无路可走,或者找到目标,或者找到所有的钥匙。
代码如下:
01.
#include<cstdio>
02.
#include<cstring>
03.
#include<algorithm>
04.
#include<queue>
05.
using
namespace
std;
06.
struct
node
07.
{
08.
int
x;
09.
int
y;
10.
}n1,n2;
11.
int
dx[4]={0,0,1,-1};
12.
int
dy[4]={1,-1,0,0};
13.
int
k[6];
14.
int
m,n;
15.
int
begin_x,begin_y;
16.
char
map[25][25];
17.
bool
vis[25][25];
18.
bool
judge(
int
x,
int
y)
19.
{
20.
if
(x<0||x>=m||y<0||y>=n||vis[x][y])
return
false
;
21.
if
(map[x][y]==
'X'
)
return
false
;
22.
if
(map[x][y]>=
'a'
&&map[x][y]<=
'e'
) k[map[x][y]-
'a'
]--;
23.
return
true
;
//其他的所有情况都返回true,都要加入队列
24.
}
25.
bool
bfs()
26.
{
27.
memset
(vis,
false
,
sizeof
(vis));
28.
queue<node>q;
29.
n1.x=begin_x;
30.
n1.y=begin_y;
31.
q.push(n1);
32.
vis[n1.x][n1.y]=
true
;
//除门之外所有的点都要进行标记
33.
while
(!q.empty())
34.
{
35.
n2=q.front();
36.
q.pop();
37.
if
(map[n2.x][n2.y]==
'G'
)
return
true
;
38.
if
(map[n2.x][n2.y]>=
'A'
&&map[n2.x][n2.y]<=
'E'
)
39.
{
40.
if
(k[map[n2.x][n2.y]-
'A'
]==0) map[n2.x][n2.y]=
'.'
;
//说明钥匙已经全部找到了
41.
else
42.
{
43.
if
(q.empty())
return
false
;
44.
else
45.
{
46.
q.push(n2);
//不进行标记,可以多次走,并且不再从此点进行搜索
47.
continue
;
48.
}
49.
}
50.
}
51.
for
(
int
i=0;i<4;i++)
52.
{
53.
n1.x=n2.x+dx[i];
54.
n1.y=n2.y+dy[i];
55.
if
(judge(n1.x,n1.y))
56.
{
57.
q.push(n1);
58.
vis[n1.x][n1.y]=
true
;
59.
}
60.
}
61.
}
62.
return
false
;
63.
64.
}
65.
int
main()
66.
{
67.
while
(
scanf
(
"%d%d"
,&m,&n)!=EOF&&m+n)
68.
{
69.
for
(
int
i=0;i<m;i++)
70.
scanf
(
"%s"
,map[i]);
71.
memset
(k,0,
sizeof
(k));
//用来保存钥匙的数量
72.
for
(
int
i=0;i<m;i++)
73.
for
(
int
j=0;j<n;j++)
74.
{
75.
if
(map[i][j]==
'S'
)
76.
{
77.
begin_x=i;
78.
begin_y=j;
79.
}
80.
if
(map[i][j]>=
'a'
&&map[i][j]<=
'e'
) k[map[i][j]-
'a'
]++;
81.
}
82.
if
(bfs())
printf
(
"YES\n"
);
83.
else
printf
(
"NO\n"
);
84.
}
85.
return
0;
86.
}