1. 程式人生 > 其它 >狀態BFS

狀態BFS

最近做各種各樣的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;
}