问题 B: 八数码问题–搜索树
题目描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。
给出一种初始状态S0和目标状态Sg,请找到一种最少步骤的移动方法,实现从初始状态S0到目标状态Sg的转变。
输入
输入测试次数t
对于每次测试,首先输入一个初始状态S0,一行九个数字,空格用0表示。然后输入一个目标状态Sg,一行九个数字,空格用0表示。
输出
只有一行,该行只有一个数字,表示从初始状态S0到目标状态Sg需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)
样例输入
2
283104765
123804765
283104765
283164705
样例输出
4
1
代码
#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <cstring>
using namespace std;
struct node
{
string chess;
int move;
};
int s1[4]={
-1,1,0,0};
int s2[4]={
0,0,-1,1};
class Solution
{
public:
node start,end;
int num;//移动次数
vector<node> visit;//装载已经访问过的结点
queue<node> list;//装状态结点的队列
void get_next(int x,int y,node temp1,int index)//将自己的子状态图塞入队列
{
if(x>=0&&x<=2&&y>=0&&y<=2){
int a=x*3+y;//得到交换点的一维坐标
char tempchar[10]={
0};
strcpy(tempchar,temp1.chess.c_str());
char c=tempchar[index];
tempchar[index]=tempchar[a];
tempchar[a]=c;
string upstring(tempchar);
node t1;
t1.chess=upstring;
t1.move=temp1.move+1;
if(!isexist(t1))//如果这个棋盘没出现过
list.push(t1);
}
}
bool isexist(node t)
{
for(int i=0;i<visit.size();i++)
if(t.chess.compare(visit[i].chess)==0)return true;
return false;
}
int find(string temp)
{
for(int i=0;i<temp.length();i++)
if(temp[i]=='0')return i;
}
int Serach()
{
list.push(start);
while(!list.empty()){
if(list.front().chess.compare(end.chess)==0)//达到目标状态
return list.front().move;
visit.push_back(list.front());//标记已经访问过
int index=find(list.front().chess);//一维的0的坐标
int x=index/3,y=index%3;
for(int i=0;i<4;i++)
get_next(x+s1[i],y+s2[i],list.front(),index);//将自己的子状态图塞入队列
list.pop();//移出队列
}
}
};
int main()
{
int t;
cin >> t;
while(t--){
Solution problem;
cin >> problem.start.chess;
cin >> problem.end.chess;
problem.start.move=0;
cout << problem.Serach() << endl;
}
return 0;
}
目的
一个笔记(写的有点复杂)