(1)将初始状态加入队列
(2)初始状态出队,进行节点扩展。可能是状态转移,列出状态转移方程
(3)在进行扩展中,需要判断节点不要重复扩展。基本思路是设立visited[]数组,标记状态是否被访问过。将状态用一个整数表示,整数则可以是数组下标,该数组下标对应的数组元素的值即是状态是否被访问的标志。即:状态-》整数-》数组下标-》数组元素的值,参考八数码中的康托展开。
(4)在扩展中,判断是否到达目标状态,如果是,则跳出循环,得出结果,问题有解;若果不是,重复(3),直到队列为空,问题无解。
以hdu1548为例
#include<iostream> #include<cstring> #include<queue> using namespace std; int steps[205]={0}; bool visited[205]={0}; struct stateNode{ int index; //状态标示符 int cost; //到达这一状态的当前代价 }; int bfs(int start,int end,int n); int main(){ int n,start,end,temp; cin>>n; while(n){ memset(steps,0,sizeof(steps)); memset(visited,1,sizeof(visited));//一定要注意memset函数是以字节为单位进行赋值,所以将visited数组设为布尔型,而不是int型,不只是省空间 cin>>start>>end; for(int i=1;i<=n;i++){ cin>>steps[i]; } if(start==end) cout<<0<<endl; else cout<<bfs(start,end,n)<<endl; cin>>n; } return 0; } int bfs(int start,int end,int n){ queue<stateNode> q; stateNode s={start,0}; q.push(s); visited[start]=0; while(!q.empty()){ stateNode first=q.front(); q.pop(); //开始扩展 stateNode nextUp=first; nextUp.index =first.index+steps[first.index];//状态转移 if(nextUp.index<=n&&visited[nextUp.index]){//符合扩展条件 nextUp.cost++; visited[nextUp.index]=false;//设置为访问过 //找到目标节点,跳出 if(nextUp.index==end){ return nextUp.cost; } else{//没有找到目标节点,继续扩展 q.push(nextUp); } } stateNode nextDown=first; nextDown.index=first.index-steps[first.index]; if(nextDown.index>=1&&visited[nextDown.index]){ nextDown.cost++; visited[nextDown.index]=false; if(nextDown.index==end) return nextDown.cost; else{ q.push(nextDown); } } } return -1; }
代码已AC
参考文献
有关bfs的题目