http://acm.nyist.net/JudgeOnline/problem.php?pid=82
#include <stdio.h>
#include <memory.h>
#define M 25
typedef struct{
int x;
int y;
int num;
}Move;
Move move[4]={{-1,0,0},{0,1,0},{1,0,0},{0,-1,0}},door[6];//保存门的坐标
int m,n,key[5],find[5],visit[M][M],arr[5],flag;
char g[M][M];
void check();
void dfs(int x,int y);
void check()
{
int a,b,i,j,k;
for(i=0;i<5;i++)
{
if(door[i].num) //如果有门的话 (门的坐标存在)
{
a=door[i].x;
b=door[i].y;
if(find[i]==key[i]) // 钥匙都找到了 并且以前到过这里 或者现在在这里(能到达门这个位置)
{
dfs(a,b);
}
}
}
}
void dfs(int x,int y)
{
visit[x][y]=1;
int i,j,k,a,b;
if(!flag)
{
for(i=0;i<4;i++)
{
a=x+move[i].x;
b=y+move[i].y;
if(a>=0&&a<m&&b>=0&&b<n&&g[a][b]!='X'&&!visit[a][b])
{
if(g[a][b]=='.')
{
dfs(a,b);
continue;
}
if(g[a][b]>='a'&&g[a][b]<='e')// 找到钥匙后 可以继续走或者去开门
{
find[g[a][b]-'a']++;
dfs(a,b);
check();// 看能否开
}
if(g[a][b]>='A'&&g[a][b]<='E')
{
door[g[a][b]-'A'].num++; //门存在 且到达了
door[g[a][b]-'A'].x=a;
door[g[a][b]-'A'].y=b;
visit[a][b]=1; //心塞!!! 有走过一定要标记阿 !!!
check();// 看能否开
}
if(g[a][b]=='G')
{
visit[a][b]=1;
flag=1;
break;
}
}
}
}
}
int main()
{
int i,j,k,x,y,s1,s2,g1,g2;
while(scanf("%d%d",&m,&n)&&(m||n))
{
flag=0;
memset(door,0,sizeof(door));
memset(visit,0,sizeof(visit));
memset(key,0,sizeof(key)); //钥匙个数
memset(find,0,sizeof(find));//找到个数
for(i=0;i<m;i++)
{
scanf("%s",g[i]);
for(j=0;j<n;j++)
{
if(g[i][j]>='a'&&g[i][j]<='e')
{
key[g[i][j]-'a']++; //需要钥匙的数量
}
if(g[i][j]=='S')
{
s1=i;
s2=j;
}
}
}
dfs(s1,s2);
if(flag)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}