这道题,用floodfill做的,首先floodfill把所有能走到的点走完,然后统计找到的钥匙数量,如果某个门的钥匙全部找到,就把相应的门打开,重新floodfill,直到达到G点或者不能再扩展。
注意本题每行后有若干空格,我就是没有注意这点,被玩了几个小时……
#include<iostream>
using namespace std;
char map[21][21];
int h,w;
bool visit[21][21];
int num[6],cnt[6],open[6],sx,sy,ex,ey;
bool flag=0;
bool ok(int x,int y)//是否可达
{
if(x>=1&&x<=h&&y>=1&&y<=w&&!visit[x][y]&&map[x][y]!='X'&&(map[x][y]<'A'||map[x][y]>'E'))
return 1;
return 0;
}
int searchdoor(int q)//打开门
{
int i,j;
for(i=1;i<=h;i++)
{
for(j=1;j<=w;j++)
{
if(map[i][j]=='A'+q-1)
map[i][j]='.';
}
}
open[q]=1;
return 0;
}
bool iskey(int x,int y)//判断是否为钥匙
{
if(map[x][y]>='a'&&map[x][y]<='e')
return 1;
return 0;
}
int floodfill(int x,int y)//灌水
{
bool canmove=0;
if(x==ex&&y==ey)
{
flag=1;
return 0;
}
visit[x][y]=1;
if(iskey(x,y))
{
cnt[map[x][y]-'a'+1]++;
}
if(ok(x+1,y))
{
canmove=1;
floodfill(x+1,y);
}
if(ok(x-1,y))
{
canmove=1;
floodfill(x-1,y);
}
if(ok(x,y+1))
{
canmove=1;
floodfill(x,y+1);
}
if(ok(x,y-1))
{
canmove=1;
floodfill(x,y-1);
}
if(!canmove)
{
int i;
for(i=1;i<=5;i++)
{
if(cnt[i]>0&&cnt[i]==num[i]&&!open[i])
{
searchdoor(i);
memset(visit,0,sizeof(visit));
memset(cnt,0,sizeof(cnt));
floodfill(sx,sy);
}
}
}
}
int main()
{
while(cin>>h>>w)
{
if(h==0&&w==0)
break;
memset(visit,0,sizeof(visit));
memset(map,'\0',sizeof(map));
memset(num,0,sizeof(num));
memset(cnt,0,sizeof(num));
memset(open,0,sizeof(open));
int i,j;
for(i=1;i<=h;i++)
{
for(j=1;j<=w;j++)
{
cin>>map[i][j];
if(map[i][j]=='S')
{
sx=i;
sy=j;
}
if(map[i][j]=='G')
{
ex=i;
ey=j;
}
if(map[i][j]>='a'&&map[i][j]<='e')
{
num[map[i][j]-'a'+1]++;
}
}
}
flag=0;
floodfill(sx,sy);
if(flag)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
system("pause");
return 0;
}