zoukankan      html  css  js  c++  java
  • 八数码

    void CEightDlg::OnBnClickedButton2()
    {
        // TODO: 在此添加控件通知处理程序代码
        CString  all = (_T(""));
        MessageBox(first) ;
        all += first ;
        std::vector<char>vec ;
        vec.clear() ;
        for(int i = 0 ;i < Str.GetLength() ;i++)
            vec.push_back(Str.GetAt(i)) ;
        class Node *start ;
        class App  *app ;
        start = new Node(vec) ;
        app = new App(*start) ;
        std::vector<CString> answer = app->out() ;
        for(int i = 0 ;i < answer.size() ;i++){
            MessageBox(answer[i]) ;
            all += answer[i] ;
        }
        MessageBox(all) ;
        delete start ;
        delete app ;
    }

     Node.h

    class Node{
        public :
            char mat[3][3] ;
            int  x ;
            int  y ;
            int  h ;  //h(x)=递归层数
            int  g ;  //g(x)=曼哈顿距离和
            int  f ;  //估价函数 f(x) = g(x)+ h(x)
            int  id ; //hash值,用于判重,利用排列序列的康拓展开
            int  G() ;//求g(x)
            int  cango() ; //剪枝,为什么逆序数必须是偶数,网上很多人问这个问题。
                           //我的解答: 与X(空白)交换的Y ,编号(index)相差为偶数,即在[ index[X] + 1 .index[Y]-1 ] 区间的数为偶数 ;
                           // 交换前  ,设  [ index[X] + 1 .index[Y]-1 ](zh) ,〉Y有a个,<Y 有b个 ,则a+b为偶数 ;
                           // 交换后  ,逆序数相较之前 +b -a  ,即| 逆序数交换前 -逆序数交换后 | 为偶数 。
                           // 也就是说无论何种交换,逆序数的变化差值为偶数 ,而最终的状态12345678X   。 (X可看作为9) ,逆序数为0。
                           // 即只能从逆序数为偶数的状态转移  。
            int  Hash() ;  // 求id
            void out() ;
            Node turn(char) ;
            Node();
            ~Node(void);
            Node(std::vector<char>) ;
            friend bool operator < (const Node &A ,const Node &B){
                 if(A.f != B.f)
                    return A.f > B.f ;
                 else
                    return A.g > B.g ;
            }             //建堆,使用C++ STL 优先队列 ,f(x)=g(x)+h(x) , f(x)小的优先级别大,也就是说与最后的状态差异小的优先考虑
    };

    Node.cpp

    #include "Node.h"
    const int fac[9] = {1,1,2,6,24,120,720,5040,40320} ;
    const int end_pos[10][2] = {{0,0},{0,0},{0,1},{0,2},
                                     {1,0},{1,1},{1,2},
                                     {2,0},{2,1},{2,2}}  ;  //最后状态  123
                                                            //          456
                                                            //          78X
    Node::Node(void)
    {
    }
    
    Node::~Node(void)
    {
    }
    
    Node::Node(std::vector<char>s){
        int i , j ;
        for(int k = 0 ;k < s.size() ;k++){
           i = k/3 ;
           j = k%3 ;
           if(s[k] == 'x'){
               this->x = i ;
               this->y = j ;
           }
           mat[i][j] = s[k] ;
        }
    }
    
    Node Node::turn(char x){
        Node ans = *this ;
        int i = ans.x ;
        int j = ans.y ;
        if(x=='l'){
            ans.x = i ;
            ans.y = j - 1 ;
            std::swap(ans.mat[i][j] ,ans.mat[i][j-1]) ;
        }
        else if(x=='r'){
            ans.x = i ;
            ans.y = j + 1 ;
            std::swap(ans.mat[i][j] ,ans.mat[i][j+1]) ;
        }
        else if(x=='d'){
            ans.x = i + 1;
            ans.y = j ;
            std::swap(ans.mat[i][j] ,ans.mat[i+1][j]) ;
        }
        else if(x=='u'){
            ans.x = i -1 ;
            ans.y = j  ;
            std::swap(ans.mat[i][j] ,ans.mat[i-1][j]) ;
        }
        return ans ;
    }
    
    int Node::G(){
        int sum = 0 ;
        for(int i = 0 ;i <= 2 ;i++){
          for(int j = 0 ;j <= 2 ;j++){
             if(mat[i][j]=='x')
               continue ;
             int n = mat[i][j] - '0' ;
             sum = sum + abs(i-end_pos[n][0]) + abs(j - end_pos[n][1]) ;
          }
        }
        return  sum ;
    }
    
    int Node::cango(){
        char num[10] ;
        int n = 0 ,sum = 0;
        for(int i = 0 ;i <=2 ;i++){
            for(int j = 0 ;j <= 2 ;j++){
                if(mat[i][j] != 'x')
                   num[++n] = mat[i][j] ;
            }
        }
        for(int i = 1 ;i <= n ;i++){
            for(int j =1 ;j < i ;j++){
                if(num[j] > num[i])
                   sum++ ;
            }
        }
        return (sum&1) == 0 ;
    }
    
    
    int Node::Hash(){
        char num[10] ;
        int n = 0 ,sum ,index = 0 ;
        for(int i = 0 ;i <=2 ;i++){
            for(int j = 0 ;j <= 2 ;j++)
                   num[n++] = mat[i][j] ;
        }
        for(int i = 0 ;i < n ;i++){
            sum = 0 ;
            for(int j =0 ;j < i ;j++){
                if(num[j] > num[i])
                   sum++ ;
            }
            index += fac[i]*sum ;
        }
        return  index ;
    }
    
    void Node::out(){
        for(int i = 0 ;i <= 2 ;i++){
            for(int j = 0 ;j <= 2 ;j++)
                putchar(mat[i][j]) ;
            puts("") ;
        }
    }

    App.h

    #include "Node.h"
    class App{
      private :
        bool visited[363000] ;
        Node start ;
        char opet[363000] ;
      public :
        App() ;
        ~App(void);
        App(class Node) ;
        int cango(int ,int) ;
        int A_star() ;
        std::vector<CString> out() ;
    };

    App.cpp

    #include "App.h"
    #include <queue>
    const char direction[4] = {'d','u','r','l'} ;     //输出记录
    const int d[4][2] = {{1,0},{-1,0},{0,1},{0,-1}} ; //四个方向
    int father[363000]  ;
    
    App::App(void)
    {
    }
    
    
    App::~App(void)
    {
    }
    
    App::App(class Node s){
        start = s ;
        start.h = 0 ;
        start.g = start.G() ;
        start.f = start.g + start.h ;
        start.id = start.Hash() ;
        memset(visited,0,sizeof(visited)) ;
        visited[start.id] = 1 ;
    }
    
    int App::cango(int x ,int y){
        return 0<=x&&x<=2&&0<=y&&y<=2 ;
    }
    
    int App::A_star(){
        if(start.id == 0)
            return 1 ;
        if(!start.cango())
            return  0;
        std::priority_queue<Node>que ;
        que.push(start) ;
        while(!que.empty()){
            Node now =que.top() ;
            que.pop() ;
            if(now.id == 0)
               return 1 ;
            for(int i = 0 ;i < 4 ;i++){
               int x = now.x + d[i][0] ;
               int y = now.y + d[i][1] ;
               if(!cango(x,y))
                 continue ;
               Node next = now ;
               next.x = x ;
               next.y = y ;
               std::swap(next.mat[now.x][now.y],next.mat[next.x][next.y]) ;
               next.id = next.Hash() ;
               if(visited[next.id])
                  continue ;
               visited[next.id] = 1 ;
               if(!next.cango())
                  continue ;
               next.g = next.G() ;
               next.h = now.h +1  ;
               next.f = next.g + next.h ;
               father[next.id] = now.id ;
               opet[next.id] = direction[i] ;
               que.push(next) ;
            }
        }
        return 0 ;
    }
    
    std::vector<CString> App::out(){
        std::vector<CString> result ;
        result.clear() ;
        if(A_star()==0){
            result.push_back(_T("无解")) ;
            return result ;
        }
        else{
            Node now = start ;
            std::vector<char>ans ;
            ans.clear() ;
            int i = 0 ;
            while(start.id != i){
                ans.push_back(opet[i]) ;
                i = father[i] ;
            }
            for(int i = ans.size()-1 ;i >= 0 ;i--){
                CString s ;
                if(ans[i]=='l')
                   s = _T("此步方向为[左]:状态如下
    ") ;
                else if(ans[i]=='r')
                   s = _T("此步方向为[右]:状态如下
    ") ;
                else if(ans[i]=='d')
                   s = _T("此步方向为[下]:状态如下
    ")  ;
                 else if(ans[i]=='u')
                   s = _T("此步方向为[上]:状态如下
    ")  ;
               now = now.turn(ans[i]) ;
               for(int ii = 0 ;ii <=2 ;ii++){
                  for(int jj = 0 ;jj <= 2 ;jj++)
                      s+= now.mat[ii][jj] ;
                  s+='
    ' ; 
               }
               result.push_back(s) ;
            }
            return result ;
        }
    }
  • 相关阅读:
    jQuery 选择器:元素选择器、#id 选择器、.class 选择器
    jQuery 语法:文档就绪事件
    jQuery 安装:多种方法在网页中添加 jQuery
    jQuery 简介:什么事jQuery?为什么要学jQuery?
    SQL 快速参考:SQL语句语法
    SQL FORMAT() 函数:对字段的显示进行格式化
    Mybatis-Plus逻辑删除
    Mybatis-Plus中的ActiveRecord
    Mybatis-Plus使用Oracle的序列
    SpringBoot整合Mybatis-Plus
  • 原文地址:https://www.cnblogs.com/liyangtianmen/p/3457913.html
Copyright © 2011-2022 走看看