POJ1077 Eight A*

这个题扔到A*可也还行。。。


定义估价函数h():为每个数或空格的位置 到 最终状态中所在位置 的 曼哈顿距离 的 总和。

把状态压成一个九进制数,便于存储和判重。

然后记录方案可以记录一下此次的操作和上一次的状态,具体见代码。

安利一篇博文:http://www.cnblogs.com/goodness/archive/2010/05/04/1727141.html 。。。被震惊。。。我只会map,懒得哈希QWQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<map>
#include<algorithm>
#define R register int
const int dx[]={-1,0,1,0},dy[]={0,1,0,-1},end=54480996;
const int py[]={0,1,2,0,1,2,0,1},px[]={0,0,0,1,1,1,2,2};
const char op[4]={'u','r','d','l'};
using namespace std;
inline int g() {
    R ret=0; register char ch; while(!isdigit(ch=getchar()));
    do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret;
}
struct node{ int sta,g,h; node() {}
    node(int ss,int gg,int hh) {sta=ss,g=gg,h=hh;}
    bool operator <(const node& y) const {return g+h>y.g+y.h;}
}; int a[3][3];
map<int,int> d,pre,dir;
priority_queue<node> q;
inline bool ckpos(int x,int y) {return x<0||x>2||y<0||y>2;}
inline int calc(int p[3][3]) { R ret=0;
    for(R i=0;i<3;++i) for(R j=0;j<3;++j) ret=ret*9+p[i][j]; return ret;
}
inline pair<int,int> recalc(int vl,int p[3][3]) { R x,y;
    for(R i=2;i>=0;--i) for(R j=2;j>=0;--j) {
        p[i][j]=vl%9,vl/=9; if(p[i][j]==0) x=i,y=j;
    } return make_pair(x,y);
}
inline int h(int p[3][3]) { R ret=0;
    for(R i=0;i<3;++i) for(R j=0;j<3;++j) {
        if(p[i][j]==0) continue;
        ret+=abs(i-px[p[i][j]-1])+abs(j-py[p[i][j]-1]);
    } return ret;
}
inline int Astar() {
    d.clear(),pre.clear(),dir.clear();
    while(q.size()) q.pop(); R st=calc(a); d[st]=0;
    q.push(node(st,0,h(a)));
    while(q.size()) {
        node u=q.top(); R crt=q.top().sta; q.pop();
        if(crt==end) return u.g;
        R a[3][3]; register pair<int,int> blk=recalc(crt,a); R x=blk.first,y=blk.second;
        for(R i=0;i<4;++i) { R xx=x+dx[i],yy=y+dy[i];
            if(ckpos(xx,yy)) continue; swap(a[x][y],a[xx][yy]);
            R nxt=calc(a); if(d.find(nxt)==d.end()||d[nxt]>d[crt]+1) 
                d[nxt]=d[crt]+1,pre[nxt]=crt,dir[nxt]=i,q.push(node(nxt,d[nxt],h(a)));//此处存了nxt的上一个状态和如何操作
            swap(a[xx][yy],a[x][y]);
        }
    } return -1;
}
inline void print(int s) {
    if(pre.find(s)==pre.end()) return;
    print(pre[s]); putchar(op[dir[s]]);
}
signed main() {
    for(R i=0;i<3;++i) for(R j=0;j<3;++j) { register char ch;
        while(!isdigit(ch=getchar())&&ch!='x');
        if(ch=='x') a[i][j]=0;
        else a[i][j]=ch^48;
    } R ans=Astar(); if(ans==-1) printf("unsolvable"),putchar('\n'); else print(end);
}

2019.04.27

 

posted @ 2019-04-27 15:24  LuitaryiJack  阅读(397)  评论(0编辑  收藏  举报