• 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('
    '); else print(end);
    }

    2019.04.27

  • 相关阅读:
    随机小错2_0527
    随计小错
    C++实现读写文件
    03-树2 List Leaves (25 分)
    获取毫秒级的时间戳
    new对象时,类名后加括号与不加括号的区别
    FoxMail 7.2的邮件存储目录修改
    C/C++ 开源算法库
    VS2015的安装
    脏内存导致BUG的问题
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10778887.html
Copyright © 2020-2023  润新知