狀態BFS
阿新 • • 發佈:2021-07-30
最近做各種各樣的BFS題目(八數碼,翻硬幣,倒水問題,數字格子問題),方法大致是一樣的,於是我整理成了自創演算法狀態BFS。
下面舉例用數字格子問題(這道題題號148,前面3個題號對應另外三題)
原理和BFS差不多,用node結構體儲存一個狀態,用string儲存狀態,比如把:
7 6 5 8
2 3 4 1
改成
"76582341"。
node還要儲存steps表示第幾步。
因為這些題都問的是步數(有的還有做不到的情況),所以我們定義BFS是int。這裡我們用map<string,bool>(倒水直接用二維陣列)來表示狀態是否出現過,防止重複計算,導致超時。
然後我們可以分幾個函式來表示狀態的變化,最後在bfs裡面檢查,如果可以新增就新增。
程式碼(加了註釋):
#include<iostream> #include<map> #include<queue>//標頭檔案 using namespace std; string st;//初始狀態 const string end="12348765";//目標狀態 map<string,bool> mp;//去重 struct node{ string str; int steps;//狀態和步數 }t,noww;//noww是現在狀態,t是輔助儲存 queue<node> q;//BFS必須用的 void shuru(){//專門用一個輸入 char c; for(int i=1;i<=8;i++){ cin>>c; st+=c; } } string l,a,b,c;//l省空間就避免重複定義,a,b,c是儲存下面三個結果的 string sxjh(string now){//上下交換 l=""; for(int i=4;i<8;i++) l+=now[i]; for(int i=0;i<4;i++) l+=now[i]; return l; } string xypy(string now){//向右平移 l=now[3]; for(int i=0;i<3;i++) l+=now[i]; l+=now[7]; for(int i=4;i<7;i++) l+=now[i]; return l; } string zjxz(string now){//中間旋轉 l=now[0]; l+=now[5]; l+=now[1]; l+=now[3]; l+=now[4]; l+=now[6]; l+=now[2]; l+=now[7]; return l; } int bfs(){//狀態BFS q.push(node{st,0});//初始狀態 while(!q.empty()){ noww=q.front(); //cout<<"aba:"<<noww.str<<endl; if(noww.str==end){//就是目標狀態,直接結束 return noww.steps; } q.pop(); a=sxjh(noww.str);//分別存這三種結果 b=xypy(noww.str); c=zjxz(noww.str); //cout<<a<<","<<b<<","<<c<<endl; if(!mp[a]){//沒有出現過 mp[a]=1;//標記為出現過 t.str=a; t.steps=noww.steps+1;//設定狀態 q.push(t);//加入佇列 } if(!mp[b]){//同上 mp[b]=1; t.str=b; t.steps=noww.steps+1; q.push(t); } if(!mp[c]){//同上 mp[c]=1; t.str=c; t.steps=noww.steps+1; q.push(t); } } return -1;//沒有找到(雖然不可能,但是以防萬一)就返回-1 } int main(){ shuru();//輸入 cout<<bfs()<<endl;//直接輸出結果,如果可能做不到就要專門加一個判斷是不是-1 return 0; }