試題 歷屆試題 九宮重排
資源限制
時間限制:1.0s 內存限制:256.0MB
問題描述
如下面第一個圖的九宮格中,放着 1~8 的數字卡片,還有一個格子空着。與空格子相鄰的格子中的卡片可以移動到空格中。經過若干次移動,可以形成第二個圖所示的局面。
我們把第一個圖的局面記爲:12345678.
把第二個圖的局面記爲:123.46758
顯然是按從上到下,從左到右的順序記錄數字,空格記爲句點。
本題目的任務是已知九宮的初態和終態,求最少經過多少步的移動可以到達。如果無論多少步都無法到達,則輸出-1。
輸入格式
輸入第一行包含九宮的初態,第二行包含九宮的終態。
輸出格式
輸出最少的步數,如果不存在方案,則輸出-1。
樣例輸入
12345678.
123.46758
樣例輸出
3
樣例輸入
13524678.
46758123.
樣例輸出
22
#include <bits/stdc++.h>
using namespace std;
char begin[3][3],end[3][3];
int move[4][2] = {1,0,-1,0,0,1,0,-1};
map<int,int> map_1;
struct node{
int step;
char ch[3][3];
node(int step_init,char ch_init[3][3]){
step = step_init;
for(int i = 0;i < 3;i++)
for(int j = 0;j < 3;j++)
ch[i][j] = ch_init[i][j];
}
};
int book(char str[3][3]){//每一種狀態都對應一個數
int result = 0;
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
if(str[i][j] != '.')
result = result*10+(str[i][j]-'0');
else
result = result*10+9;
}
}
return result;
}
bool check(char str[3][3]){//檢查是否到達結束狀態
for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++){
if(str[i][j] != end[i][j]){
return false;
}
}
}
return true;
}
int bfs(){
int res = -1;
queue<node> q;
q.push(node(0,begin));
map_1[book(q.front().ch)] = 1;
while(!q.empty()){
node n1 = q.front();
q.pop();
int x = -1,y = -1;
for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++){
if(n1.ch[i][j] == '.'){
x = i;
y = j;
break;
}
}
if(x != -1 && y != -1) break;
}
for(int i = 0;i < 4;i++){
node n2 = n1;
int xx = x + move[i][0];
int yy = y + move[i][1];
if(xx < 0 || yy < 0 || xx == 3 || yy == 3) continue;
swap(n2.ch[xx][yy],n2.ch[x][y]);
if(map_1[book(n2.ch)] == 1) continue;
map_1[book(n2.ch)] = 1;
n2.step = n1.step + 1;
if(check(n2.ch) == true){
res = n2.step;
return res;
}
q.push(n2);
}
}
return res;
}
int main(){
string str1,str2;
cin>>str1>>str2;
int index = 0;
for(int i = 0;i < 3;i++)
{
for(int j = 0;j < 3;j++)
{
begin[i][j] = str1[index];
end[i][j] = str2[index];
index++;
}
}
int res = bfs();
cout<<res<<endl;
return 0;
}