[藍橋杯]九宮重排

[C++]九宮重排

九宮重排:
如下面第一個圖的九宮格中,放着 1~8 的數字卡片,還有一個格子空着。與空格子相鄰的格子中的卡片可以移動到空格中。經過若干次移動,可以形成第二個圖所示的局面。
我們把第一個圖的局面記爲:12345678.
把第二個圖的局面記爲:123.46758
顯然是按從上到下,從左到右的順序記錄數字,空格記爲句點。
本題目的任務是已知九宮的初態和終態,求最少經過多少步的移動可以到達。如果無論多少步都無法到達,則輸出-1
輸入格式:
輸入第一行包含九宮的初態,第二行包含九宮的終態。
輸出格式:
輸出最少的步數,如果不存在方案,則輸出-1。

輸入:
12345678.
123.46758
輸出:
3

解題思路:可以使用bfs,由於時間限制,需要使用雙向bfs,對初態和終態進行bfs,當兩邊狀態變化到一種形態時,表示可以達到。即maps值爲1,是由初態變化而來,爲2的話,是由終態變化而來。當maps值相加爲3的時候,則證明初態和終態都能達到此狀態。

#include<iostream>
#include<map>
#include<queue>
#include<string>
using namespace std;

int ne[4][2] = {1,0,-1,0,0,1,0,-1};
map<string, int> maps;
map<string, int> temp;
string a, b;

/*
	雙向bfs 
*/
int bfs(){
	if(a == b)
		return 0;
	queue<string> que;
	que.push(a);
	que.push(b);
	while(!que.empty()) {
		string head = que.front();
		que.pop();
		
		char t;
		int x, y;
		for(int i = 0; i<3; i++){
			for(int j = 0; j<3; j++){
				t = i*3+j;
				if(head[t] == '.'){
					x = i;
					y = j;
					break;
				}
			}
		}
		t = x*3+y;
		for(int i = 0; i<4; i++){
			int nx = x + ne[i][0];
			int ny = y + ne[i][1];
			if(nx>=0 && nx<3 && ny>=0 && ny < 3){
				string tail = head;
				tail[t] = head[nx*3+ny];
				tail[nx*3+ny] = head[t];
				if(!maps[tail]) {
					maps[tail] = maps[head];   //區分由a轉化而來還是由b轉化而來 
					temp[tail] = temp[head]+1; //移動步數加1 
					que.push(tail);
				}
				else if(maps[tail] + maps[head] == 3){
					return temp[tail]+temp[head]+1;
				}
			}
		}
	}
	return -1;
}

int main(){
	cin>>a>>b;
	/**
	初始化  由a轉化而來的maps值爲1  由b轉化來的maps值爲2 
	*/ 
	maps[a] = 1;
	maps[b] = 2;
	
	cout<<bfs()<<endl;
	
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章