题意:7数码问题。在2×4的棋盘上,摆有7个棋子,每个棋子上标有1至7的某一数字,不同棋子上标的数字不相同。棋盘上还有一个空格(用0表示),与空格相邻(上下左右)的棋子可以移到空格中,该棋子原先位置成为空格。给出一个初始状态(保证可以转移到最终状态),找出一种从初始状态转变成给定最终状态的移动棋子步数最少的移动步骤。
输入:多组输入,每组8个数,表示初始状态前四个数为第一行从左到右,后四个数为第二行从左到右。
输出:至少需要多少步可以从输入状态到达最终状态(0 1 2 3 4 5 6 7)
(题意翻译参考自http://bbs.byr.cn/#!article/ACM_ICPC/73337?au=Milrivel)
(图1)
(图2)
(图3)
分析:格子的数量较少可以把01234567作为起点开始BFS直到排列形式变成和样例相同(打表的话更快)
收获:BFS是可以双向搜索的,既可以从末状态到初状态,也可以反过来进行。按照查找的目的不同可以在队列保存的数据类型可能不同,这里是要判断整个界面的最终结果,queue中再保存Point(x,y)肯定是不合适的,并且没法判断。queue里保存的类型应该是与搜索的目的相关联的。
#include<iostream>
#include<queue>
#include <map>
using namespace std;
string s;
map<string, int > mp;
int d[]={1,-1,4,-4};
void bfs()
{
queue<string>que;
que.push("01234567");
while(que.size())
{
string s1=que.front();
que.pop();
int pos=0;
// cout << s1 <<endl;
for(int i=0; i<8; i++)
{
if(s1[i]=='0')
{
pos=i;
break;
}
}
for(int i=0; i<4; i++)
{
int x=pos+d[i];
if(x>=0&&x<8&&(!(pos == 3 && i == 0) && !(pos == 4 && i == 1)) )
{
// cout << endl<< pos <<endl ;
string u=s1;
swap(u[pos],u[x]);
if(mp[u]==0)
{
mp[u]=mp[s1]+1;
que.push(u);
}
}
}
}
return ;
}
int main ()
{
int in;
bfs();
while (true)
{ mp["01234567"]=0;
s="";
for (int i = 0; i < 8; i++)
{
if (!(cin >> in))return 0;
s += in + '0';
}
cout << mp[s]<< endl;
}
return 0;
}