题目链接~~>
思路:先用 dfs( ) 找钥匙,再用 bfs( ) 找门(如果在找钥匙或找门的过程中发现宝藏则结束),找到门时看一下钥匙是否足够,如果打开一扇门接着 dfs( ) 去寻找钥匙(有可能打开一扇门里面有钥匙),一直寻找完。
代码:
#include<stdio.h> #include<string.h> #include<queue> using namespace std ; int n,m,f,mkey ; // mkey 找到钥匙的数量 int g[10],vis[25][25],vix[25][25][100] ; // 广搜时每增加一个钥匙就可以走回头路 int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1} ; // 和胜利大逃亡(续)思想一样 char s[25][25] ; struct zhang { int x,y ; } ; int search(int x,int y)//判断是否满足条件 { if((s[x][y]>='A'&&s[x][y]<='E')||s[x][y]=='X') return 0 ; if(x<0||x>=n||y<0||y>=m||vis[x][y]) return 0 ; if(s[x][y]>='a'&&s[x][y]<='e')//找到一把钥匙则对应钥匙减一 { int k=s[x][y]-'a' ; g[k]-- ; mkey++ ; } return 1 ; } void dfs(int i,int j)// 深搜找钥匙 { if(s[i][j]=='G'||f) { f=1 ;return ;} if(search(i-1,j)) { vis[i-1][j]=1 ;dfs(i-1,j) ;} if(search(i+1,j)) { vis[i+1][j]=1 ;dfs(i+1,j) ;} if(search(i,j-1)) { vis[i][j-1]=1 ;dfs(i,j-1) ;} if(search(i,j+1)) { vis[i][j+1]=1 ;dfs(i,j+1) ;} } int bfs(int x,int y)// 广搜找门 { queue<zhang>q ; zhang current,next ; memset(vix,0,sizeof(vix)) ; current.x=x ; current.y=y ; vix[x][y][mkey]=1 ; q.push(current) ; while(!q.empty()) { current=q.front() ; q.pop() ; if(s[current.x][current.y]=='G'||f) return 1 ; for(int i=0;i<4;i++) { next.x=current.x+dx[i] ; next.y=current.y+dy[i] ; if(next.x>=0&&next.x<n&&next.y>=0&&next.y<m&&s[next.x][next.y]!='X'&&!vix[next.x][next.y][mkey]) { vix[next.x][next.y][mkey]=1 ; if(s[next.x][next.y]>='A'&&s[next.x][next.y]<='E') { int key=s[next.x][next.y]-'A' ; if(!g[key]) { s[next.x][next.y]='.' ; dfs(next.x,next.y) ; q.push(next) ; } } else q.push(next) ; } } } return 0 ; } int main() { int i,j,rx,ry ; while(scanf("%d %d",&n,&m)!=EOF) { if(!n&&!m) break ; memset(g,0,sizeof(g)) ; memset(vis,0,sizeof(vis)) ; for(i=0;i<n;i++) { scanf("%s",s[i]) ; for(j=0;j<m;j++) { if(s[i][j]=='S') { rx=i ; ry=j ; } else if(s[i][j]>='a'&&s[i][j]<='e')//储存钥匙 { int k=s[i][j]-'a' ; g[k]++ ; } } } f=0 ;mkey=0 ; vis[rx][ry]=1 ; dfs(rx,ry) ; if(f) { printf("YES\n") ; continue ; } int mx=bfs(rx,ry) ; if(mx!=0) printf("YES\n") ; else printf("NO\n") ; } return 0 ; }