题目描述
初始状态的步数就算1,哈哈
输入:第一个3*3的矩阵是原始状态,第二个3*3的矩阵是目标状态。
输出:移动所用最少的步数
Input
2 8 3
1 6 4
7 0 5
1 2 3
8 0 4
7 6 5
Output
6
分析:
因为要找到最少的步数,所以采用BFS,且由于题目的要求是矩阵到达目标状态,因此每次矩阵变形后都要记录其变形后的状态与目标状态比较,并且记录当前状态的步数。设置一个队列,把起始状态放入其中,读出起始状态,并判断可行的变换状态,再将变换状态放入队列,直到找到符合目标状态的矩阵。但是如果仅仅只是这样不做优化,会导致空间不够,因为总是反复读入之前已经遇到的状态。
要点:
每次保存状态时放入之前状态变换的位置,在这次变换时,若是变换为之前的状态,判断为不可行的变换;
使用Hash表,保存不同状态的访问信息,每次变换时判断其状态是否被访问过,若被访问过判定为不可行的变换。
方法一:加入之前变换的信息
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
char End[3][3];
int ki[4] = {0, -1, 0, 1};
int kj[4] = {-1, 0, 1, 0};
struct eightshu{
char mp[3][3];
int i, j, step;
int prei, prej;
};
eightshu temp;
bool Match(char a[3][3]){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(a[i][j] != End[i][j]) return false;
}
}
return true;
}
bool Judge(int i, int j){
if(i >= 0 && i < 3 && j >= 0 && j < 3) return true;
else return false;
}
void Copy(char a[3][3]){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
temp.mp[i][j] = a[i][j];
}
}
}
int BFS(eightshu n){
queue<eightshu> q;
q.push(n);
while(!q.empty()){
eightshu now = q.front();
q.pop();
for(int i = 0; i < 4; i++){
temp.i = now.i + ki[i];
temp.j = now.j + kj[i];
if(Judge(temp.i, temp.j)){
if(temp.i == now.prei && temp.j == now.prej) continue;
temp.step = now.step + 1;
Copy(now.mp);
swap(temp.mp[temp.i][temp.j], temp.mp[now.i][now.j]);
temp.prei = now.i;
temp.prej = now.j;
}else{
continue;
}
if(Match(temp.mp)){
return temp.step;
}else{
q.push(temp);
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
eightshu n;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
cin >> n.mp[i][j];
if(n.mp[i][j] == '0'){
n.i = i;
n.j = j;
n.prei = i;
n.prej = j;
}
}
}
n.step = 1;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
cin >> End[i][j];
}
}
int step = BFS(n);
cout << step << '\n';
return 0;
}
方法二:使用Hash表记录之前的状态
#include <iostream>
#include <queue>
#include <algorithm>
#include <map>
using namespace std;
char End[3][3];
int ki[4] = {0, -1, 0, 1};
int kj[4] = {-1, 0, 1, 0};
struct eightshu{
char mp[3][3];
int i, j, step;
};
eightshu temp;
map <int, bool> H;
int Hash(char a[][3]){
int index = 0;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
index *= 10;
index += a[i][j] - '0';
}
}
return index;
}
bool Match(char a[3][3]){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
if(a[i][j] != End[i][j]) return false;
}
}
return true;
}
bool Judge(int i, int j){
if(i >= 0 && i < 3 && j >= 0 && j < 3) return true;
else return false;
}
void Copy(char a[3][3]){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
temp.mp[i][j] = a[i][j];
}
}
}
int BFS(eightshu n){
H[Hash(n.mp)] = true;
queue<eightshu> q;
q.push(n);
while(!q.empty()){
eightshu now = q.front();
q.pop();
for(int i = 0; i < 4; i++){
temp.i = now.i + ki[i];
temp.j = now.j + kj[i];
if(Judge(temp.i, temp.j)){
temp.step = now.step + 1;
Copy(now.mp);
swap(temp.mp[temp.i][temp.j], temp.mp[now.i][now.j]);
if(H[Hash(temp.mp)] == true) continue;
else H[Hash(temp.mp)] = true;
}else{
continue;
}
if(Match(temp.mp)){
return temp.step;
}else{
q.push(temp);
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
eightshu n;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
cin >> n.mp[i][j];
if(n.mp[i][j] == '0'){
n.i = i;
n.j = j;
}
}
}
n.step = 1;
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
cin >> End[i][j];
}
}
int step = BFS(n);
cout << step << '\n';
return 0;
}