• A*算法(八数码问题)


    #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;
    }
    


  • 相关阅读:
    18-行列式及其性质
    17-正交矩阵和Gram-Schmidt正交化
    14-正交向量与子空间
    centOS7.3 离线安装docker
    10-四个基本子空间
    使用vim打造python-ide
    09-线性相关性、基、维数
    python小实例
    Elasticsearch学习之ES节点类型以及各种节点的分工
    基于Kibana和ES的苏宁实时日志分析平台
  • 原文地址:https://www.cnblogs.com/riasky/p/3430683.html
Copyright © 2020-2023  润新知