POJ 1077 && HDU 1043 Eight A*算法,bfs,康托展开,hash 难度:3

http://poj.org/problem?id=1077

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

X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0!。这就是康托展开。康拓展开可以用来表示排列状态,对于本题的9个数字的所有排列只需要9位,所有状态总共362880个.对每个状态,我们都能得到一个不重复的状态编号,用这个状态编号可以查重

Astar算法,就是一个给所有状态一个评估函数,优先选取较优状态向下搜的最好优先直接搜索算法,对于本题,我们设F(n)=g(n)+h(n)为估价函数,设g(n)为到达该状态已经走过的步数,h(n)为到最终答案的曼哈顿距离

因为该拼图不能改变除了x以外的数字的逆序数奇偶性,所以若x以外的数字逆序数为奇数,则无法得到答案,直接输出

 

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <queue>

#include <cctype>

using namespace std;

const int base[9]={1,1,2,6,24,120,720,5040,40320};

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

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

const int maxh=362880;

const int des=0;

struct pnt{

        int maz[3][3];

        int h,g;

        int x,y;

        int hashCode;

        bool operator < (pnt p)const {

                return h+g!=p.h+p.g?h+g>p.h+p.g:g>p.g;

        }

        int gethashcode(){

                int ans=0;

                for(int i=0;i<9;i++){

                        int cnt=0;

                        for(int j=0;j<i;j++){

                                if(maz[j/3][j%3]>maz[i/3][i%3]){

                                        cnt++;

                                }

                        }

                        ans+=base[i]*cnt;

                }

                return hashCode=ans;

        }

        int geth(){

                int ans=0;

                for(int i=0;i<3;i++){

                        for(int j=0;j<3;j++){

                                int t=maz[i][j]-1;

                               if(t<9) ans+=abs(i-t/3)+abs(j-t%3);

                        }

                }

                return ans;

        }

        bool judge(){

                int cnt=0;

                for(int i=0;i<9;i++){

                        for(int j=0;j<i;j++){

                                if(maz[i/3][i%3]<9&&maz[j/3][j%3]<9&&maz[i/3][i%3]<maz[j/3][j%3])cnt++;

                        }

                }

                return (cnt&1)==0;

        }

};

bool in(int tx,int ty){

        return tx>=0&&tx<3&&ty>=0&&ty<3;

}



int vis[maxh+1];

int pre[maxh+1];



void astar(pnt s){

        priority_queue <pnt>que;

        que.push(s);

        while(!que.empty()){

                pnt f=que.top();que.pop();

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

                        pnt t=f;

                        t.x+=dx[i];

                        t.y+=dy[i];

                        if(in(t.x,t.y)){

                                swap(t.maz[t.x][t.y],t.maz[f.x][f.y]);

                                t.hashCode=t.gethashcode();

                                if(vis[t.hashCode]==-1){

                                        vis[t.hashCode]=i;

                                        t.g++;

                                        pre[t.hashCode]=f.hashCode;

                                        t.h=t.geth();

                                        que.push(t);

                                }

                                if(t.hashCode==des)return ;

                        }

                }

        }

}

char ans[maxh+1];

void print(){

        int nxt=des;

        int len=0;

        while(pre[nxt]!=-1){

               switch(vis[nxt]){

               case 0:

                       ans[len++]='d';

                break;

               case 1:

                       ans[len++]='u';

                break;

               case 2:

                       ans[len++]='r';

                break;

               case 3:

                       ans[len++]='l';

                break;

               }

               nxt=pre[nxt];

        }

        for(int i=len-1;i>=0;i--){

                putchar(ans[i]);

        }

        puts("");

}

char buff[300];

pnt s;

bool input(){

        if(gets(buff)==NULL)return false;

        int j=0;

        for(int i=0;i<9;i++){

                while(!isalnum(buff[j])){j++;}

                if(buff[j]>='0'&&buff[j]<='9'){

                        s.maz[i/3][i%3]=buff[j]-'0';

                }

                else{

                        s.maz[i/3][i%3]=9;

                        s.x=i/3;

                        s.y=i%3;

                }

                j++;

        }

        return true;

}

int main(){

        while(input()){

                memset(vis,-1,sizeof(vis));

                memset(pre,-1,sizeof(pre));

                if(!s.judge()){

                        puts("unsolvable");

                        continue;

                }

                s.hashCode=s.gethashcode();

                if(s.hashCode==des){

                        puts("");

                        continue;

                }

                vis[s.hashCode]=-2;

                s.g=0;s.h=s.geth();

                astar(s);

                print();

        }

        return 0;

}

  

你可能感兴趣的:(hash)