#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
#include <conio.h>
#include <cstdlib>
#include <algorithm>
#include <windows.h>
using namespace std;
#define DIRECTION int
const char TEST_END = '0';
const int BOARDSIZE = 3;
const int TABLESIZE = 370000;
const int DIRECTION_SIZE = 4;
const int INIT_POS_IN_HASH = -1;
const int INIT_PARENT = -1;
const int INIT_START = -1;
const int INIT_G = 1;
const int G_GROW = 1;
const char BLANK = 'X';
enum VISITESTATE{ NOTFOUND, INOPEN, INCLOSE };
const int hashArr[9] = { 7, 17, 47, 117, 217, 977, 1299, 5971, 7779 };
const int dir_x[DIRECTION_SIZE] = { -1, 1, 0, 0 };
const int dir_y[DIRECTION_SIZE] = { 0, 0, -1, 1 }; //Up Down Left Right struct position{
position(){}
position(int xx, int yy):x(xx),y(yy){}
int x;
int y;
}; position finalPosition[BOARDSIZE * BOARDSIZE]; struct ChessBoard{
ChessBoard(){
visitState = NOTFOUND;
posInHashTable = INIT_POS_IN_HASH;
}
ChessBoard& operator = ( const ChessBoard& cb ){
for( int i = 0; i < BOARDSIZE; ++i ){
for( int j = 0; j < BOARDSIZE; ++j ){
this->ChessState[i][j] = cb.ChessState[i][j];
}
}
this->blankX = cb.blankX;
this->blankY = cb.blankY;
this->g = cb.g;
this->h = cb.h;
this->direction = cb.direction;
this->parent = cb.parent;
this->posInHashTable = cb.posInHashTable;
return *this;
}
friend bool operator < ( const ChessBoard& a, const ChessBoard& b ){
return ( a.g + a.h ) > ( b.g + b.h );
}
char ChessState[BOARDSIZE][BOARDSIZE];
VISITESTATE visitState;
int blankX;
int blankY;
int g;
int h;
int direction;
int posInHashTable;
int parent;
}; ChessBoard hashTable[TABLESIZE]; class AStarAlg{
public:
AStarAlg(){
finalState.ChessState =
{
{ '1', '2', '3' },
{ '4', '5', '6' },
{ '7', '8', BLANK }
};
initChessBoard();
}
void initChessBoard();
void AStar();
void printPath( ChessBoard );
void showChessBoard( const ChessBoard& ) const;
const ChessBoard& getChessBoard( int index ){ return hashTable[index]; };
const ChessBoard& getInitalChessBoard(){ return initState; };
private:
bool isSolvable( const ChessBoard& );
bool getNextChessBoard( ChessBoard& nextState, const ChessBoard& parentState, const DIRECTION& );
int hashCal( ChessBoard& );
void setInOpen( ChessBoard& );
void updateOpen( const ChessBoard& );
bool isInOpen( const ChessBoard& ) const;
void setInClose( ChessBoard& );
bool isNotFound( const ChessBoard& ) const;
bool isInClose( const ChessBoard& ) const;
void calHeuristic( ChessBoard& );
void calG( ChessBoard& );
void calFun( ChessBoard& );
bool isEqual( const ChessBoard&, const ChessBoard& ); vector< ChessBoard >openTable;
ChessBoard initState;
ChessBoard finalState;
}; bool AStarAlg::isSolvable( const ChessBoard& cb ){
char* tempArr = new char[BOARDSIZE * BOARDSIZE + 1];
const int length = BOARDSIZE * BOARDSIZE;
int count = 0;
int countNum = 0;
for( int i = 0; i < BOARDSIZE; ++i ){
for( int j = 0; j < BOARDSIZE; ++j ){
if( initState.ChessState[i][j] == BLANK ) tempArr[count] = '9';
else tempArr[count] = initState.ChessState[i][j];
count++;
}
}
for( int i = 0; i < length; ++i ){
const int base = tempArr[i] - '0';
for( int j = 0; j < i; ++j ){
const int cmp = tempArr[j] - '0';
if( cmp > base ) countNum++;
}
}
delete tempArr;
if( countNum % 2 != 0 ) return false;
return true;
} void AStarAlg::setInOpen( ChessBoard& cb ){
cb.visitState = INOPEN;
hashTable[cb.posInHashTable].visitState = INOPEN;
openTable.push_back( cb );
push_heap( openTable.begin(), openTable.end() );
} void AStarAlg::printPath( ChessBoard cb ){
if( cb.parent == INIT_PARENT ){
cout<<"Finsh."<<endl;
return;
}
vector<ChessBoard>path;
while( true ){
path.push_back( cb );
if( cb.parent == INIT_PARENT ) break;
cb = hashTable[cb.parent];
}
for( int i = path.size() - 1; i >= 0; --i ){
showChessBoard( path[i] );
}
} void AStarAlg::updateOpen( const ChessBoard& cb ){
for( int i = 0; i < openTable.size(); ++i ){
if( isEqual( openTable[i], cb ) ){
openTable[i] = cb;
break;
}
}
make_heap( openTable.begin(), openTable.end() );
} void AStarAlg::setInClose( ChessBoard& cb ){
hashTable[cb.posInHashTable].visitState = INCLOSE;
cb.visitState = INCLOSE;
} bool AStarAlg::isInClose( const ChessBoard& cb ) const{
return ( hashTable[cb.posInHashTable].visitState == INCLOSE ) ? true : false;
} bool AStarAlg::isInOpen( const ChessBoard& cb ) const{
return ( hashTable[cb.posInHashTable].visitState == INOPEN ) ? true : false;
} bool AStarAlg::isNotFound( const ChessBoard& cb ) const{
return ( hashTable[cb.posInHashTable].visitState == NOTFOUND ) ? true : false;
} //Manhattan distance (state : AC)
void AStarAlg::calHeuristic( ChessBoard& cb ){
int h = 0;
for( int i = 0; i < BOARDSIZE; ++i ){
for( int j = 0; j < BOARDSIZE; ++j ){
int val = cb.ChessState[i][j] - '0';
int x = finalPosition[val - 1].x;
int y = finalPosition[val - 1].y;
h += abs( i - x ) + abs( j - y );
}
}
cb.h = h;
} void AStarAlg::calG( ChessBoard& cb ){
if( cb.parent == INIT_PARENT ){ // caution : == =
cb.g = INIT_G;
}
else{
cb.g = hashTable[cb.parent].g + G_GROW;
}
} void AStarAlg::calFun( ChessBoard& cb ){
calHeuristic( cb );
calG( cb );
} void AStarAlg::initChessBoard(){
cout<<"Enter inital State : ";
string str;
getline( cin, str );
int count = 0;
for( int i = 0; i < str.length(); ++i ){
if( str[i] != ' ' ){
initState.ChessState[count / BOARDSIZE][count % BOARDSIZE] = str[i];
if( str[i] == 'x' ){
initState.ChessState[count / BOARDSIZE][count % BOARDSIZE] = BLANK;
initState.blankX = count / BOARDSIZE;
initState.blankY = count % BOARDSIZE;
}
++count;
}
}
initState.direction = INIT_START;
initState.parent = INIT_PARENT;
calFun( initState );
int pos = hashCal( initState );
openTable.push_back( initState );
make_heap( openTable.begin(), openTable.end() );
} //is equal with each other ( state : AC )
bool AStarAlg::isEqual( const ChessBoard& cbA, const ChessBoard& cbB ){
for( int i = 0; i < BOARDSIZE; ++i ){
for( int j = 0; j < BOARDSIZE; ++j ){
if( cbA.ChessState[i][j] != cbB.ChessState[i][j] ) return false;
}
}
return true;
} // function: calculate the position of the state of chessboard in hashTable
// if the state has been existing ( INOPEN , INCLOSE ) then return its position is hashTble
// else set the state in hashTable and then return its position
// PS: must after all operation ( my drawback )
int AStarAlg::hashCal( ChessBoard& cb ){
int pos = 0;
for( int i = 0; i < BOARDSIZE; ++i ){
for( int j = 0; j < BOARDSIZE; ++j ){
//'x'
int val = cb.ChessState[i][j] - '0';
pos += val * hashArr[ BOARDSIZE * i + j ];
}
}
pos = pos % TABLESIZE;
while( hashTable[pos].visitState != NOTFOUND ){
if( isEqual( hashTable[pos], cb ) ){
cb.posInHashTable = pos;
return pos;
}
pos = ( pos + 1 ) % TABLESIZE;
}
cb.posInHashTable = pos;
hashTable[pos] = cb;
return pos;
} //Just get next chess board state from its parent state ( state : AC )
bool AStarAlg::getNextChessBoard( ChessBoard& tempNextState,
const ChessBoard& parentState,
const DIRECTION& dir ){
//Get temp next chess board blank_x and blank_y
int tempNextBlankX = parentState.blankX + dir_x[dir];
int tempNextBlankY = parentState.blankY + dir_y[dir];
if( tempNextBlankX < 0 || tempNextBlankX > BOARDSIZE - 1
|| tempNextBlankY < 0 || tempNextBlankY > BOARDSIZE - 1 ) return false; tempNextState.blankX = tempNextBlankX;
tempNextState.blankY = tempNextBlankY;
tempNextState.direction = dir;
//Get temp next chess board state
for( int i = 0; i < BOARDSIZE; ++i ){
for( int j = 0; j < BOARDSIZE; ++j ){
tempNextState.ChessState[i][j] = parentState.ChessState[i][j];
}
}
char change = tempNextState.ChessState[tempNextState.blankX][tempNextState.blankY];
tempNextState.ChessState[parentState.blankX][parentState.blankY] = change;
tempNextState.ChessState[tempNextState.blankX][tempNextState.blankY] = BLANK;
//Get temp next chess board parent position
tempNextState.parent = parentState.posInHashTable;
//Get temp next chess board g and h, its parent state has got
calFun( tempNextState );
//Hash Cal
hashCal( tempNextState );
return true;
} void AStarAlg::AStar(){
char c;
while( !openTable.empty() ){
pop_heap( openTable.begin(), openTable.end() );
ChessBoard parent = openTable.back();
if( !isSolvable( parent ) ){
cout<<"unsolvable"<<endl;
return;
}
openTable.erase( openTable.end() - 1 );
setInClose( parent );
// showChessBoard( parent );
//c = getch();
if( isEqual( parent, finalState ) ){
printPath( parent );
return;
}
for( int i = 0; i < DIRECTION_SIZE; ++i ){
ChessBoard tempNextState;
if( !getNextChessBoard( tempNextState, parent, i ) ) continue;
if( isNotFound( tempNextState ) ){
setInOpen( tempNextState );
continue;
}
if( isInOpen( tempNextState ) ){
int f = tempNextState.g + tempNextState.h;
if( f < hashTable[tempNextState.posInHashTable].g + hashTable[tempNextState.posInHashTable].h ){
hashTable[tempNextState.posInHashTable] = tempNextState;
updateOpen( tempNextState );
continue;
}
}
if( isInClose( tempNextState ) ){
int f = tempNextState.g + tempNextState.h;
if( f < hashTable[tempNextState.posInHashTable].g + hashTable[tempNextState.posInHashTable].h ){
hashTable[tempNextState.posInHashTable] = tempNextState;
setInOpen( tempNextState );
continue;
}
}
}
}
cout<<"unsolveable"<<endl;
} //Show information of chess board ( State : AC )
void AStarAlg::showChessBoard( const ChessBoard& cb ) const{
cout<<endl;
cout<<"<<<<<<<<<<<<<<<<<<<<<< Pandora >>>>>>>>>>>>>>>>>>>>>"<<endl;
cout<<"ChessBoard State : "<<endl;
for( int i = 0; i < BOARDSIZE; ++i ){
for( int j = 0; j < BOARDSIZE; ++j ){
cout<<cb.ChessState[i][j]<<" ";
}
cout<<endl;
}
cout<<"Blank_X : "<<cb.blankX<<" "<<"Blank_Y : "<<cb.blankY<<endl;
cout<<"Position is HashTable : "<<cb.posInHashTable<<endl;
cout<<"Parent : "<<cb.parent<<endl;
cout<<"G : "<<cb.g<<" "<<"H : "<<cb.h<<" "<<"F : "<<cb.h + cb.g<<endl;
switch( cb.visitState ){
case NOTFOUND:{
cout<<"Now my state : Not be found."<<endl;
break;
}
case INOPEN:{
cout<<"Now my state : In open table."<<endl;
break;
}
case INCLOSE:{
cout<<"Now my state : In close"<<endl;
break;
}
default:{
cout<<"Error state!"<<endl;
break;
}
}
cout<<"<<<<<<<<<<<<<<<<<<<<<< Pandora >>>>>>>>>>>>>>>>>>>>>"<<endl;
cout<<endl;
} //Get the fianl chess board state ( State : AC )
void preWork(){
int count = 0;
for( int i = 0; i < BOARDSIZE; ++i ){
for( int j = 0; j < BOARDSIZE; ++j ){
position temp;
temp.x = i;
temp.y = j;
finalPosition[count] = temp;
count++;
}
}
} int main(){
preWork();
AStarAlg a;
a.AStar();
return 0;
}

A*算法(八数码问题)的更多相关文章

  1. A*算法 -- 八数码问题和传教士过河问题的代码实现

    前段时间人工智能的课介绍到A*算法,于是便去了解了一下,然后试着用这个算法去解决经典的八数码问题,一开始写用了挺久时间的,后来试着把算法的框架抽离出来,编写成一个通用的算法模板,这样子如果以后需要用到 ...

  2. noj 算法 八数码问题

    描述 在九宫格里放在1到8共8个数字还有一个是空格,与空格相邻的数字可以移动到空格的位置,问给定的状态最少需要几步能到达目标状态(用0表示空格):1 2 34 5 67 8 0   输入 输入一个给定 ...

  3. HDU 1043 八数码(A*搜索)

    在学习八数码A*搜索问题的时候须要知道下面几个点: Hash:利用康托展开进行hash 康托展开主要就是依据一个序列求这个序列是第几大的序列. A*搜索:这里的启示函数就用两点之间的曼哈顿距离进行计算 ...

  4. A*算法解决八数码问题 Java语言实现

    0X00 定义 首先要明确一下什么是A*算法和八数码问题? A*(A-Star)算法是一种静态路网中求解最短路径最有效的直接搜索方法也是一种启发性的算法,也是解决许多搜索问题的有效算法.算法中的距离估 ...

  5. HUD 1043 Eight 八数码问题 A*算法 1667 The Rotation Game IDA*算法

    先是这周是搜索的题,网站:http://acm.hdu.edu.cn/webcontest/contest_show.php?cid=6041 主要内容是BFS,A*,IDA*,还有一道K短路的,.. ...

  6. HDU 1043 Eight 八数码问题 A*算法(经典问题)

    HDU 1043 Eight 八数码问题(经典问题) 题意 经典问题,就不再进行解释了. 这里主要是给你一个状态,然后要你求其到达\(1,2,3,4,5,6,7,8,x\)的转移路径. 解题思路 这里 ...

  7. Java实现 蓝桥杯 算法提高 八数码(BFS)

    试题 算法提高 八数码 问题描述 RXY八数码 输入格式 输入两个33表格 第一个为目标表格 第二个为检索表格 输出格式 输出步数 样例输入 1 2 3 4 5 6 7 8 0 1 2 3 4 5 6 ...

  8. 八数码难题之 A* 算法

    人生第一个A*算法-好激动-- 八数码难题--又称八数码水题,首先要理解一些东西: 1.状态可以转化成整数,比如状态: 1 2 3 4 5 6 7 8 0 可以转化成:123456780这个整数 2. ...

  9. 【C++算法设计】八数码问题

    八数码问题 [题意] 编好为1~8的8个正方形滑块摆成3行3列(一个格子为空),如图所示 每次可以移动空格相邻的滑块到空格,要计算出能移动出目标局面的最小步数,如无法达到则输出-1. [分析] 我们可 ...

  10. 【算法】BFS+哈希解决八数码问题

    15拼图已经有超过100年; 即使你不叫这个名字知道的话,你已经看到了.它被构造成具有15滑动砖,每一个从1到15上,并且所有包装成4乘4帧与一个瓦块丢失.让我们把丢失的瓷砖“X”; 拼图的目的是安排 ...

随机推荐

  1. JAVA 对象内存分析

    1.jmap -heap pid 或者 jmap -histo pid 2.jmap -dump:file=folder/dumpFileName.txt,format=b pid 3.对3的输出文件 ...

  2. 一次搞懂 Assets Pipeline 转载自http://gogojimmy.net/2012/07/03/understand-assets-pipline/

    Assets Pipeline 是 Rails 3.1 一個重要的功能,一直並沒有很去了解其特性,但因為最近都在寫前端的東西在 assets pipeline 的東西上跌跌撞撞了不少次(尤其在 dep ...

  3. codevs 1515 跳 贪心+lucas

    题目链接 一个人初始在(0, 0), 想到(n, m)去, 没到一个格子, 花费的值为C(n, m), 求最小值. C(n, m)的定义为, 如果n==0||m==0, 则为1, 否则C(n, m) ...

  4. c 结构体 简单的了解

    1.声明一个学生类的 结构体 struct Student{ int age; char name[20];//长度为20的字符串 int weiht;//像正常一样的申请变量,这个变量属于结构体的一 ...

  5. PowerShell Remove all user defined variable in PowerShell

    When PS scripts executes, it is possibly create much user defined variables. So, sometimes these var ...

  6. Sublime Text 2 - There are no packages available for installation

    解决Sublime Text 2 package Control 无法安装插件的问题 错误提示 here are no packages available for installation 问题解决 ...

  7. c++ enum用法【转】

    1.为什么要用enum       写程序时,我们常常需要为某个对象关联一组可选alternative属性.例如,学生的成绩分A,B,C,D等,天气分sunny, cloudy, rainy等等.   ...

  8. CERC 2013 Magical GCD

    题目大意如下:给定一个序列,每个序列有值xi,现给定t个数列,对于每个长n的数列,求一段[l,r]使 [r-l+1]*gcd(l,r)最大,gcd(l,r)指的是该连续区间的最大公约数. 不难想到n^ ...

  9. PE框架学习之道:PE框架——发送报文流程

    PE框架发送报文,适用于PE及VX技术 步骤: 1.在action中使用发送报文,要指定报文在router端的交易名称 2.如果使用supe.execute(context)来发送,不需要第一步 3. ...

  10. OFbiz--HelloWorld

    上篇博客<OFbiz--简单介绍>我们介绍了OFbiz是什么,以下我们就開始用OFbiz开发我们的第一个程序--HelloWorld. 过程例如以下: 首先在hot-deploy下新建文件 ...