Description
Yours和zero在研究A*启发式算法.拿到一道经典的A*问题,但是他们不会做,请你帮他们.
问题描述
在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局(初始状态)和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。
Solution
八数码问题,题意日常裸
为了显示出些进步,我们用启发式搜索A*解决这一题
关键就在于估价函数。这里我们用所有数字错位的欧拉距离之和作为f,然后一串字符串可以拆成3*3的矩阵处理移动,又压回1*9的字符串。为了去重这里直接用stl的map了
经常性打错重载比较符,想死
Code
#include <iostream>
#include <string>
#include <queue>
#include <cmath>
#include <map>
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define L 9
using std:: string;
struct data{
string s;
int f, g;
bool operator <(data b)const{
data a = *this;
return a.f > b.f;
}
};
struct pos{
int x, y;
pos operator +(pos b)const{
pos a = *this;
return (pos){a.x + b.x, a.y + b.y};
}
}dir[4] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
int rc[L][L];
inline int cmp(string a, string b){
int tot = 0;
rep(i, '0', '8'){
tot += rc[a.find(i)][b.find(i)];
}
return tot;
}
inline void swap(char &a, char &b){
char c = a;
a = b;
b = c;
}
using std:: priority_queue;
priority_queue<data>heap;
using std:: map;
map<string, bool> hash;
using std:: cout;
using std:: endl;
inline int bfs(string st, string ed){
heap.push((data){st, cmp(st, ed), 0});
hash[st] = true;
while (!heap.empty()){
data now = heap.top(); heap.pop();
// cout << now.s << endl;
if (now.s == ed){
return now.g;
}
int p = now.s.find('0');
int x = p / 3;
int y = p % 3;
pos nowPos = (pos){x, y};
rep(k, 0, 3){
pos tarPos = nowPos + dir[k];
if (tarPos.x >= 0 && tarPos.x < 3 && tarPos.y >= 0 && tarPos.y < 3){
string tar = now.s;
swap(tar[nowPos.x * 3 + nowPos.y], tar[tarPos.x * 3 + tarPos.y]);
if (hash[tar] == false){
hash[tar] = true;
heap.push((data){tar, now.g + 1 + cmp(tar, ed), now.g + 1});
}
}
}
}
}
using std:: cin;
using std:: abs;
int main(void){
std:: ios:: sync_with_stdio(false);
/*
string a, b;
cin >> a >> b;
cout << cmp(a, b) << endl;
return 0;
*/
rep(i, 0, 2){
rep(j, 0, 2){
rep(k, 0, 2){
rep(l, 0, 2){
rc[i * 3 + j][k * 3 + l] = abs(i - k) + abs(j - l);
}
}
}
}
string st;
cin >> st;
string ed;
ed = "123804765";
int ans = bfs(st, ed);
cout << ans << endl;
return 0;
}