【POJ1077】八数码

这道题是洛谷“八数码难题”的升级版,洛谷只要求出最少步数,而本题要输出结果。

我们在搜索的时候记录每一个状态的前驱,最后输出的时候递归即可。

我们采用A*算法进行搜索,设计估价函数为当前状态每个点与目标状态每个点的曼哈顿距离之和。在搜索时建立一个小根堆维护即可。

代码细节比较多,注意对细节的处理。可以用pair,map简化部分代码。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <map>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <cmath>
  8 using namespace std;
  9 struct node {
 10     int val,dis;
 11     bool operator <(const node &x) const {
 12         return dis>x.dis;
 13     }
 14 };
 15 priority_queue<node> q;
 16 map<int,int> dis,fa,go;
 17 const int fx[4]={-1,0,0,1};
 18 const int fy[4]={0,-1,1,0};
 19 char dir[4]={'u','l','r','d'};
 20 int a[4][4];
 21 int calc(int a[4][4]) {
 22     int ret=0;
 23     for(int i=1;i<=3;i++)
 24         for(int j=1;j<=3;j++)
 25             ret=ret*9+a[i][j];
 26     return ret;
 27 }
 28 int value(int a[4][4]) {
 29     int ret=0;
 30     for(int i=1;i<=3;i++)
 31         for(int j=1;j<=3;j++) {
 32             if(a[i][j]==0) continue ;
 33             int x=(a[i][j]-1)/3+1;
 34             int y=(a[i][j]-1)%3+1;
 35             ret+=abs(i-x)+abs(j-y);
 36         }
 37     return ret;
 38 }
 39 pair<int,int> recalc(int val,int a[4][4]) {
 40     int x,y;
 41     for(int i=3;i>=1;i--)
 42         for(int j=3;j>=1;j--) {
 43             a[i][j]=val%9;
 44             val/=9;
 45             if(!a[i][j]) x=i,y=j;
 46         }
 47     return make_pair(x,y);
 48 }
 49 int bfs(int x,int y,int endval) {
 50     int st=calc(a);
 51     dis[st]=0;
 52     q.push(node{st,value(a)});
 53     while(!q.empty()) {
 54         int now=q.top().val;
 55         q.pop();
 56         if(now==endval) return dis[now];
 57         int a[4][4];
 58         pair<int,int> k=recalc(now,a);
 59         int nowx=k.first;
 60         int nowy=k.second;
 61         for(int i=0;i<4;i++) {
 62             int xx=nowx+fx[i];
 63             int yy=nowy+fy[i];
 64             if(xx<1||xx>3||yy<1||yy>3) continue ;
 65             swap(a[nowx][nowy],a[xx][yy]);
 66             int neww=calc(a);
 67             if(dis.find(neww)==dis.end()||dis[neww]>dis[now]+1) {
 68                 dis[neww]=dis[now]+1;
 69                 fa[neww]=now;
 70                 go[neww]=i;
 71                 q.push(node{neww,dis[neww]+value(a)});
 72             }
 73             swap(a[nowx][nowy],a[xx][yy]);
 74         }
 75     }
 76     return -1;
 77 }
 78 void print(int val) {
 79     if(fa.find(val)==fa.end()) return ;
 80     print(fa[val]);
 81     putchar(dir[go[val]]);
 82 }
 83 int main() {
 84     int end=0;
 85     for(int i=1;i<=8;i++)
 86         end=end*9+i;
 87     end*=9;
 88     int sx,sy;
 89     for(int i=1;i<=3;i++)
 90         for(int j=1;j<=3;j++) {
 91             char s[2];
 92             scanf("%s",s);
 93             if(s[0]=='x') a[i][j]=0,sx=i,sy=j;
 94             else a[i][j]=s[0]-'0';
 95         }
 96     int ans=bfs(sx,sy,end);
 97     if(ans==-1) puts("unsolvable");
 98     else print(end);
 99     return 0;
100 }
AC Code
原文地址:https://www.cnblogs.com/shl-blog/p/10630412.html