读书人

十五数码有关问题

发布时间: 2013-03-10 09:38:39 作者: rapoo

十五数码问题

做完八数码之后我还想做难一点的东西,因为八数码直接爆搜就可以了,所以想做一下爆搜不能做的东西,十五数码如果爆搜的话有15!种状态,不可能存下的;

我的思路是不存那么多状态,我把所有的状态hash到10000大小的vector数组里面,每次搜索不可能吧所有的状态都遍历完,所以不会爆内存的,然后存路径是用

链表做的,将后面扩展到的状态指向前一个状态,在搜索到的时候就从最后一个向前遍历,然后把方向存在一个栈中,输出就可以了

下面粘代码:

#include <iostream>#include <cstring>#include <queue>#include <stack>#include <cmath>#include <vector>using namespace std ;struct Node {    int   h , step ;    long long key ;    char  dir  ;    Node * pre ;} ;struct cmp {    bool operator () ( Node a , Node b  ) {        return a.h < b.h ;    }} ;long long  fac[17] ;vector < long long > Hash[10000] ;Node *END ;void  init() ;long long cantor( int s[] ) ;void  uncantor( int s[] , long long num ) ;int   h( int s[]  ) ;bool  AStar( int s[] ) ;bool  check( long long ) ;int  main(){    int   str[16] ;    char  ch ;    init() ;    memset( Hash , 0 , sizeof( Hash ) ) ;    for( int i = 0 ; i <= 15 ; i ++ )    {        cin >> ch ;        if( ch == 'x' ) str[i] = 16 ;        else if( ch >= '0' && ch <= '9' ) str[i] = ch - '0' ;        else str[i] = 10 + ch - 'A' ;    }    if( AStar( str ) )    {        stack < char > s ;        while( END->pre != NULL )        {            s.push( END->dir ) ;            END = END->pre ;        }        while( !s.empty() )        {            cout << s.top() ;            s.pop() ;        }        cout << endl ;    }    else cout << "unsolvable" << endl ;    return 0 ;}void  init(){fac[0] = 1 ;for( int i = 1 ; i <= 16 ; i ++ )fac[i] = i * fac[i-1] ;}long long  cantor( int s[] ){    long long  num = 0 , t ;    for( int i = 0 ; i < 16 ; i ++ )    {        t = 0 ;        for( int j = i + 1 ; j < 16 ; j ++ )            if( s[i] > s[j] ) t ++ ;        num += fac[16 - i - 1] * t ;    }    return num ;}void uncantor( int s[] , long long num ){long long  j , t , r ;bool p[17] ;memset( p , 0 , sizeof( p ) ) ;for( int i = 0 ; i < 16 ; i ++ ){t = num / fac[16 - i - 1] + 1 ;num %= fac[16 - i - 1] ;r = 0 , j = 1 ;while( 1 ){if( !p[j] ) r ++ ;if( r == t ) break ;j ++ ;}s[i] = j ; p[j] = 1 ;}}int  h( int s[] ){    int H = 0 ;    for( int i = 0 ; i < 16 ; i ++ )        if( s[i] != 16 && i == s[i] - 1 ) H ++ ;    return H ;}bool check( long long num ){    int key = num % 10000 ;    bool flag = 0 ;    for( int i = 0 ; i < Hash[key].size() ; i ++ )        if( Hash[key][i] == num ) {            flag = 1 ;            break ;        }    return ( 1 - flag ) ;}bool  AStar( int s[] ){    int  str[16] , flag = 0 , i ;    long long t ;    priority_queue< Node , vector< Node > , cmp > q ;    Node * start = new Node  ;    start->key  = cantor( s ) ;    start->pre  = NULL ;    start->h    = h( s ) ;    start->step = 0 ;    start->dir = '0' ;    int  num = start->key % 10000 ;    Hash[num].push_back( start->key ) ;    q.push( *start ) ;    while( !q.empty() )    {        Node * temp = new Node ;        * temp = q.top() ;        q.pop() ;        if( temp->key == 0 ){            flag = 1 ;            END = temp ;            break ;        }        uncantor( str , temp->key ) ;        for( i = 0 ; i < 16 ; i ++ ) if( str[i] == 16 ) break ;        if( i != 0 && i != 1 && i != 2 && i != 3 )        {            swap( str[i] , str[i-4] ) ;            t = cantor( str ) ;            if( check( t ) )            {                Node *tmp = new Node ;                tmp->dir  = 'u' ;                tmp->h    = h( str ) ;                tmp->key  = t ;                tmp->pre  = temp ;                tmp->step = temp->step + 1 ;                num = t % 10000 ;                Hash[num].push_back( t ) ;                q.push( *tmp ) ;            }            swap( str[i] , str[i-4] ) ;        }        if( i != 12 && i != 13 && i != 14 && i != 15 )        {            swap( str[i] , str[i+4] ) ;            t = cantor( str ) ;            if( check( t ) )            {                Node *tmp = new Node ;                tmp->dir  = 'd' ;                tmp->h    = h( str ) ;                tmp->key  = t ;                tmp->pre  = temp ;                tmp->step = temp->step + 1 ;                num = t % 10000 ;                Hash[num].push_back( t ) ;                q.push( *tmp ) ;            }            swap( str[i] , str[i+4] ) ;        }        if( i != 0 && i != 4 && i != 8 && i != 12 )        {            swap( str[i] , str[i-1] ) ;            t = cantor( str ) ;            if( check( t ) )            {                Node *tmp = new Node ;                tmp->dir  = 'l' ;                tmp->h    = h( str ) ;                tmp->key  = t ;                tmp->pre  = temp ;                tmp->step = temp->step + 1 ;                num = t % 10000 ;                Hash[num].push_back( t ) ;                q.push( *tmp ) ;            }            swap( str[i] , str[i-1] ) ;        }        if( i != 3 && i != 7 && i != 11 && i != 15 )        {            swap( str[i] , str[i+1] ) ;            t = cantor( str ) ;            if( check( t ) )            {                Node *tmp = new Node ;                tmp->dir  = 'r' ;                tmp->h    = h( str ) ;                tmp->key  = t ;                tmp->pre  = temp ;                tmp->step = temp->step + 1 ;                num = t % 10000 ;                Hash[num].push_back( t ) ;                q.push( *tmp ) ;            }            swap( str[i] , str[i+1] ) ;        }    }    return flag ;}


代码略搓,写了那么多才写完。。。。

读书人网 >其他相关

热点推荐