题目链接:https://www.luogu.org/problemnew/show/P1379
题意:用字符串表示八数码,求根据给定八数码得到末状态“123804765”最少的步数。
思路:这题很方便用双向bfs来优化,用两个队列分别从起点、终点开始搜索,两个map来记录该状态的步数。要注意的是起始状态和末状态相等的情况,需要特判。
AC代码:
#include<cstdio> #include<queue> #include<algorithm> #include<string> #include<map> #include<iostream> using namespace std; struct node{ string s; int step,w; }; int go[4]={-1,1,-3,3}; queue<node> q1,q2; map<string,int> mp1,mp2; bool isOK(int w,int k){ int x=w+go[k]; if(x<0||x>8) return false; if(w%3==0&&k==0) return false; if(w%3==2&&k==1) return false; return true; } void bfs(){ while(!q1.empty()&&!q2.empty()){ node now1=q1.front();q1.pop(); string s1=now1.s; int step1=now1.step,w1=now1.w; for(int i=0;i<4;++i){ if(!isOK(w1,i)) continue; int ww=w1+go[i],st=step1+1; string ss=s1; swap(ss[w1],ss[ww]); if(mp1[ss]) continue; if(mp2[ss]){ printf("%d ",step1+mp2[ss]-1); return; } mp1[ss]=st; node tmp={ss,st,ww}; q1.push(tmp); } node now2=q2.front();q2.pop(); string s2=now2.s; int step2=now2.step,w2=now2.w; for(int i=0;i<4;++i){ if(!isOK(w2,i)) continue; int ww=w2+go[i],st=step2+1; string ss=s2; swap(ss[w2],ss[ww]); if(mp2[ss]) continue; if(mp1[ss]){ printf("%d ",step2+mp1[ss]-1); return; } mp2[ss]=st; node tmp={ss,st,ww}; q2.push(tmp); } } } int main(){ string s; cin>>s; if(s=="123804765"){ printf("0 "); return 0; } int w; for(int i=0;i<s.length();++i) if(s[i]=='0'){ w=i;break; } node bg={s,1,w}; node ed={"123804765",1,4}; mp1[s]=1,mp2["123804765"]=1; q1.push(bg),q2.push(ed); bfs(); return 0; }