nyoj 82 bfs 好题

来源:互联网 发布:win10跑分软件 编辑:程序博客网 时间:2024/06/05 20:19

题目链接

思路:

这个题关键在于对门的处理,一开始我的思想和标准答案的思想差不多,也是保存钥匙,然后遇到一个门 如果当前钥匙全部被找到的话就可以把这个门打开,就可以bfs这个门后面的,如果当前钥匙不够的话 如果队列为空就直接找不到,队列不为空就继续将门入队,但是不进行标记,也就是可以一直无限找到.

我写完了一发是过了,可是飞巨给我一个样例我发现我写的是不对的 但是nyoj 还是给我过了,那就是如果一开始起始点就被门包围了,图中也有钥匙和宝藏,如果这样一直入队的话就是一个死循环,可是这种情况应该是无法找到宝藏的,

是不是测序数据有点菜啊。。。。

比如 3 3 

SAa

BbG

C..   一直死循环了。。。

正解:

我认为对于这个题就应该 先遍历整个图,当遍历到门时 就把它先存起来并标记(防止重复加入队列),然后去判断这些能走到的门哪些钥匙够了,就把他们加入队列,否则不加入...就这样一直判断,如果出现上面我说的那种情况队列就为空了

  #include<bits/stdc++.h>using namespace std;int n,m;char s[22][22];int book[22][22],key[6],flag[22][22];int stx,sty;int go[4][2]={0,1,1,0,0,-1,-1,0};struct node{int x,y;}f[6],q,p;int check(int r,int c){if(r<0||r>=n||c<0||c>=m||book[r][c]==1)return 0;if(s[r][c]=='X')return 0;if(s[r][c]>='a'&&s[r][c]<='e')key[s[r][c]-'a']--;return 1;}bool bfs(){queue<node>Q;memset(book,0,sizeof(book));memset(flag,0,sizeof(flag));q.x=stx;q.y=sty;book[stx][sty]=1; Q.push(q);int k=0;while(!Q.empty()){p=Q.front();Q.pop();if(s[p.x][p.y]=='G')return true;if(s[p.x][p.y]>='A'&&s[p.x][p.y]<='E'&&!flag[p.x][p.y]){f[k++]=p;flag[p.x][p.y]=1;}else{for(int i=0;i<4;i++){int tx=p.x+go[i][0];int ty=p.y+go[i][1];if(check(tx,ty)){book[tx][ty]=1;q.x=tx;q.y=ty;Q.push(q);}}}for(int i=0;i<k;i++){if(key[s[f[i].x][f[i].y]-'A']==0&&flag[f[i].x][f[i].y]==1){   Q.push(f[i]);flag[f[i].x][f[i].y]=2;}}}return false;}int main(){ while(~scanf("%d %d",&n,&m)) { if(n==0&&m==0) break; memset(key,0,sizeof(key)); for(int i=0;i<n;i++) {  scanf("%s",s[i]);  for(int j=0;j<m;j++)  {  if(s[i][j]=='S')  {  stx=i;  sty=j;}if(s[i][j]>='a'&&s[i][j]<='e'){key[s[i][j]-'a']++;}  }}if(bfs())printf("YES\n");elseprintf("NO\n");} return 0;}                



以上只是自己一点的小见解。。。希望没说错话尴尬

0 0