A*算法解决八数码问题
2013-02-19 11:48
357 查看
昨天啃了一阵子,终于啃下了大名鼎鼎的A*(AStar)算法。
A*跟BFS(宽度优先搜索)非常相似,只是多了一个启发函数跟结点的实时判断。
而A*算法的重点也就是启发函数,而且这没有固定的模版或者套路,完全看个人的设计能力。
其他的并不难。
参考了 http://hi.baidu.com/catro/item/4782da1769edbd721109b5e9
和 http://blueve.me/archives/684
这两篇写得非常好的文章。
废话不说了,稚嫩的代码如下:
A*跟BFS(宽度优先搜索)非常相似,只是多了一个启发函数跟结点的实时判断。
而A*算法的重点也就是启发函数,而且这没有固定的模版或者套路,完全看个人的设计能力。
其他的并不难。
参考了 http://hi.baidu.com/catro/item/4782da1769edbd721109b5e9
和 http://blueve.me/archives/684
这两篇写得非常好的文章。
废话不说了,稚嫩的代码如下:
#include <iostream> #include <vector> #include <queue> using namespace std; //A*八数码 // 状态结构存储 struct State { int s[3][3]; int index,pre; int g; //打印路径 void Display() { for(int i = 0; i < 3; ++i) { for(int j = 0; j < 3; ++j) { cout << s[i][j] << ' '; } cout << endl; } } //优先级比较 friend bool operator< (State n1, State n2) { return n1.g > n2.g; } bool equal(State goal) { for(int i = 0; i < 3; ++i) { for(int j = 0; j < 3; ++j) { if(s[i][j] != goal.s[i][j]) return false; } } return true; } int fineZero(int flag) { for(int i=0;i<3;i++) for(int j=0;j<3;j++) if(s[i][j]==0) { if(flag==0) return i; else return j; } } }; //vector<State> States; // 存储所有的状态 //初始状态和目标状态 State inital,goal; //开闭表 priority_queue<State> openTable; vector<State> closeTable; int direct[4][2]={{0,1},{0,-1},{1,0},{-1,0}}; //方向 右 左 下 上 /** * 启发函数 * -------------------- * f(s) = g(s) + h(s) * 其中 g(s) 由 g 数组给出 * h(s) = 与目标状态不一致点的个数 */ int f(State node) { int rslt = node.g; // g(s) for(int i = 0; i < 3; ++i) // h(s) for(int j = 0; j < 3; ++j) { if(node.s[i][j] != goal.s[i][j]) { rslt++; } } return rslt; } bool isMove(int goalX , int goalY) { if(goalX < 0 || goalX>=3) return false; if(goalY < 0 || goalY>=3) return false; return true; } bool isCloseTableContain(State node) { State tmp; for(vector<State>::iterator ite = closeTable.begin() ; ite != closeTable.end() ;ite++) { tmp = (State)*ite; if(tmp.equal(node)) return true; } return false; } State AStar(State start) { // 初始状态 start.g = 0; start.pre = -1; openTable.push(start); while(!openTable.empty()) { // 找到最优的一个状态 State preState = openTable.top(); // 获取状态索引 openTable.pop(); // 插入close表 preState.index = closeTable.size(); closeTable.push_back(preState); // 已找到目标状态 if(preState.equal(goal)) { return preState; } // 尝试向四个方向扩展该状态 for(int i(0); i < 4; ++i) { State cur = preState; int zeroX = cur.fineZero(0); int zeroY = cur.fineZero(1); // 取得带扩展状态的空位位置 int goalX = direct[i][0]+zeroX; int goalY = direct[i][1]+zeroY; // 确保移动合法 if(isMove(goalX, goalY)) { // 交换移动0 int num = cur.s[goalX][goalY]; cur.s[goalX][goalY] = 0; cur.s[zeroX][zeroY] = num; // 判重 if(!isCloseTableContain(cur)) { // 将新状态置入状态序列 cur.g = f(cur); cur.pre = preState.index; // 插入open表 openTable.push(cur); } } } } } State inputData()//录入数据 { State aNode; for(int i=0;i<3;i++) { for(int j=0;j<3;j++) { cin>>aNode.s[i][j]; } } return aNode; } //递归回溯求解 void disPlayWay(int index) { if(index == -1) return ; State node = closeTable[index]; disPlayWay(node.pre); node.Display(); cout<<"->"<<endl; } int main() { inital = inputData(); goal = inputData(); State result = AStar(inital); cout<<"找到解答,移动步骤如下:"<<endl; disPlayWay(result.index); return 0; } /* 2 8 3 1 6 4 7 0 5 1 2 3 8 0 4 7 6 5 */
相关文章推荐
- hdu 1043 A*算法解决八数码问题
- A*算法解决八数码问题 Java语言实现
- A*算法解决八数码问题
- 用A*算法解决八数码问题 MATLAB
- A*算法解决十五数码问题
- BFS和A*算法分别解决N-数码问题
- A*算法解决八数码问题
- 启发式搜索-A*算法解决八数码问题
- A*算法解决八数码问题
- A*算法解决八数码问题 Java语言实现
- A*算法解决八数码问题时,第N步的解空间是多少?
- A*算法解决八数码(九宫重排)问题
- 算法篇-14-A*算法解决八数码问题
- A*算法解决八数码问题(C++版本)
- A*算法解决八数码问题的C++实现
- A*算法(八数码问题)
- 基于A*算法的八数码问题(九宫问题)解法的程序实现(新增有无解判断)
- A*算法实现八数码问题
- 通过八数码问题学习A*算法
- A*算法求解15数码问题