HDU 1043

http://acm.hdu.edu.cn/showproblem.php?pid=1043

http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html

根据这篇文章说的八数码八境界,我这种做法大概是在境界三。。

我选择的是康托展开作为哈希函数,在全排列问题中这个哈希函数可以很好的处理冲突

http://zh.wikipedia.org/zh/%E5%BA%B7%E6%89%98%E5%B1%95%E5%BC%80

当然白书上的那种哈希也是极好的。。

#include <iostream>

#include <queue>

#include <cstring>

using namespace std ;

int vis[1000005] ;

int f[10]={1,1,2,6,24,120,720,5040,40320,362880} ;

int ct(int *a)

{

    int ans=0 ;

    for(int i=0 ;i<8 ;i++)

    {

        int cnt=0 ;

        for(int j=i+1 ;j<9 ;j++)

            if(a[j]<a[i])

                cnt++ ;

        ans+=cnt*f[8-i] ;

    }

    return ans ;

}

typedef struct L{

    int a[10] ;

    int p,pos ;

    string step ;

}L ;

int dx[]={1,-1,0,0} ;

int dy[]={0,0,1,-1} ;

string d="udlr" ;

string ans[1000005] ;

void bfs()

{

    queue <L> q ;

    L now,next ;

    for(int i=0 ;i<8 ;i++)

        now.a[i]=i+1 ;

    now.a[8]=0 ;

    now.p=ct(now.a) ;

    now.pos=8 ;

    now.step="" ;

    ans[now.p]="" ;

    q.push(now) ;

    vis[now.p]=1 ;

    while(!q.empty())

    {

        now=q.front() ;

        q.pop() ;

        for(int i=0 ;i<4 ;i++)

        {

            int xx=now.pos/3+dx[i] ;

            int yy=now.pos%3+dy[i] ;

            if(xx<0 || xx>2 || yy<0 || yy>2)continue ;

            next=now ;

            next.pos=xx*3+yy ;

            next.a[now.pos]=next.a[next.pos] ;

            next.a[next.pos]=0 ;

            next.p=ct(next.a) ;

            if(!vis[next.p])

            {

                next.step+=d[i] ;

                vis[next.p]=1 ;

                ans[next.p]=next.step ;

                q.push(next) ;

            }

        }

    }

}

void pt(int *a)

{

    int tt=ct(a) ;

    if(!vis[tt])

    {

        puts("unsolvable") ;

        return ;

    }

    for(int i=ans[tt].length()-1 ;i>=0 ;i--)

        cout << ans[tt][i] ;

    putchar('\n') ;

}

int main()

{

    bfs() ;

    char s[101] ;

    while(gets(s))

    {

        int st=0 ;

        int t[10] ;

        for(int i=0 ;i<strlen(s) ;i++)

        {

            if(s[i]>='1' && s[i]<='8')

                t[st++]=s[i]-'0' ;

            if(s[i]=='x')

                t[st++]=0 ;

        }

        pt(t) ;

    }

    return 0 ;

}
View Code

 

你可能感兴趣的:(HDU)