[HDU] 3355 Hop — Don’t Walk! [BFS]
题目来源:HDOJ 3355 [2009 ANARC]
题目大意:给定一条由一个个小方块组成的直线小路,有一只青蛙停在其中的一块小方块上,小方块分黑白两种,分别用字母B和W表示。青蛙停的位置则由字母F表示。按一定规则操作后,使得在黑方块中没有白方块存在。规则如下:青蛙共有4种选择,假设还有路的话,可以选择前进一步(即F?变成?F,其中?代表W或B,下同),或后退一步(?F变成F?),或前进两步(F?B变成W?F),或后退两步(W?F变成F?B)。问:最少需要几步才能达到预定结果?
简单分析:首先,要说明的是题目中有提到,当步数大于10的时候,就不用再继续走了,直接输出-1就可以了。这个很关键,因为,这样一来,最多只用走9步,即便给出所有的不同的方案总共也只有4^9=262144种。所以,用BFS来遍历各种方案后的状态就可以了。不过,一开始,我超时了很多次,因为,当时在BFS中另外开设了一个set<sting> visited用来存放已有的状态,然后用visited.count(v)==0来判断是否已存在,但是这样在遍历的时候似乎加重了程序开销(具体原因,待以后分析),之后,用原本存放步数的map<string int>同时用来判断,即step.find(v)==step.end(),并且最后把原本在if语句的最终状态判断语句if(is(v)) return step[v]放到了if里面(我想这一步,也能缩短时间,因为提前可以做判断了,不过对于超过9步的数据来说是无视了),这样就能AC了,不过时间也不少,640MS。
AC代码如下:
#include<iostream> #include<map> #include<string> #include<queue> using namespace std; bool is(string s) { int i,k=0,flag=0,t=0; int n=s.size(); for(i=0;i<n;++i) { if(s[i]=='W'&&flag==1) k++; if(s[i]=='B') { flag=1; if(k!=0) { t=1; break; } } } if(t) return false; else return true; } int BFS(string s) { queue<string> Qu; int len=s.size(),f; string u,v; map<string,int> step; step[s]=0; Qu.push(s); while(!Qu.empty()) { u=Qu.front(); Qu.pop(); if(step[u]>=10) return -1; f=u.find('F'); v=u; if(f+1<len) { v[f]=v[f+1]; v[f+1]='F'; if(step.find(v)==step.end()) { step[v]=step[u]+1; if(is(v)) return step[v]; Qu.push(v); } } v=u; if(f-1>=0) { v[f]=v[f-1]; v[f-1]='F'; if(step.find(v)==step.end()) { step[v]=step[u]+1; if(is(v)) return step[v]; Qu.push(v); } } v=u; if(f+2<len) { if(v[f+2]=='B') v[f]='W'; if(v[f+2]=='W') v[f]='B'; v[f+2]='F'; if(step.find(v)==step.end()) { step[v]=step[u]+1; if(is(v)) return step[v]; Qu.push(v); } } v=u; if(f-2>=0) { if(v[f-2]=='B') v[f]='W'; if(v[f-2]=='W') v[f]='B'; v[f-2]='F'; if(step.find(v)==step.end()) { step[v]=step[u]+1; if(is(v)) return step[v]; Qu.push(v); } } } return -1; } int main() { string state; int count=1,r; while(cin>>state) { if(state[0]=='-') break; if(is(state)) cout<<count++<<". 0"<<endl; else { r=BFS(state); r==-1?cout<<count++<<". -1"<<endl:cout<<count++<<". "<<r<<endl; } } return 0; }