A - Eight

The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 x

where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:

1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8
9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12
13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x
r-> d-> r->

The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.

Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).

In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three
arrangement.

InputYou will receive, several descriptions of configuration of the 8 puzzle. One description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle

1 2 3
x 4 6
7 5 8

is described by this list:

1 2 3 x 4 6 7 5 8
OutputYou will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line. Do not print a blank line between cases.
Sample Input
2  3  4  1  5  x  7  6  8
Sample Output
ullddrurdllurdruldr


1.一种超内存的方法
复制代码
  1     /*
  2     HDU 1043 Eight
  3     思路:反向搜索,从目标状态找回状态对应的路径
  4     用康托展开判重
  5     */
  6     #include<stdio.h>
  7     #include<string.h>
  8     #include<iostream>
  9     #include<queue>
 10     #include<string>
 11     using namespace std;
 12     const int MAXN=1000000;//最多是9!/2
 13     int fac[]={1,1,2,6,24,120,720,5040,40320,362880};//康拖展开判重
 14     //         0!1!2!3! 4! 5!  6!  7!   8!    9!
 15     bool vis[MAXN];//标记
 16     string path[MAXN];//记录路径
 17     int cantor(int s[])//康拖展开求该序列的hash值
 18     {
 19         int sum=0;
 20         for(int i=0;i<9;i++)
 21         {
 22             int num=0;
 23             for(int j=i+1;j<9;j++)
 24               if(s[j]<s[i])num++;
 25             sum+=(num*fac[9-i-1]);
 26         }
 27         return sum+1;
 28     }
 29     struct Node
 30     {
 31         int s[9];
 32         int loc;//“0”的位置
 33         int status;//康拖展开的hash值
 34         string path;//路径
 35     };
 36     int move[4][2]={{-1,0},{1,0},{0,-1},{0,1}};//u,d,l,r
 37     char indexs[5]="durl";//和上面的要相反,因为是反向搜索
 38     int aim=46234;//123456780对应的康拖展开的hash值
 39     void bfs()
 40     {
 41         memset(vis,false,sizeof(vis));
 42         Node cur,next;
 43         for(int i=0;i<8;i++)cur.s[i]=i+1;
 44         cur.s[8]=0;
 45         cur.loc=8;
 46         cur.status=aim;
 47         cur.path="";
 48         queue<Node>q;
 49         q.push(cur);
 50         path[aim]="";
 51         while(!q.empty())
 52         {
 53             cur=q.front();
 54             q.pop();
 55             int x=cur.loc/3;
 56             int y=cur.loc%3;
 57             for(int i=0;i<4;i++)
 58             {
 59                 int tx=x+move[i][0];
 60                 int ty=y+move[i][1];
 61                 if(tx<0||tx>2||ty<0||ty>2)continue;
 62                 next=cur;
 63                 next.loc=tx*3+ty;
 64                 next.s[cur.loc]=next.s[next.loc];
 65                 next.s[next.loc]=0;
 66                 next.status=cantor(next.s);
 67                 if(!vis[next.status])
 68                 {
 69                     vis[next.status]=true;
 70                     next.path=indexs[i]+next.path;
 71                     q.push(next);
 72                     path[next.status]=next.path;
 73                 }
 74             }
 75         }
 76 
 77     }
 78     int main()
 79     {
 80         char ch;
 81         Node cur;
 82         bfs();
 83         while(cin>>ch)
 84         {
 85             if(ch=='x') {cur.s[0]=0;cur.loc=0;}
 86             else cur.s[0]=ch-'0';
 87             for(int i=1;i<9;i++)
 88             {
 89                 cin>>ch;
 90                 if(ch=='x')
 91                 {
 92                     cur.s[i]=0;
 93                     cur.loc=i;
 94                 }
 95                 else cur.s[i]=ch-'0';
 96             }
 97             cur.status=cantor(cur.s);
 98             if(vis[cur.status])
 99             {
100                 cout<<path[cur.status]<<endl;
101             }
102             else cout<<"unsolvable"<<endl;
103         }
104         return 0;
105     }
复制代码

2.

复制代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<iostream>
using namespace std;
const int MAXN=400000;
bool has[MAXN];
int fac[9] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int dx[] = {-1, 0, 1, 0};
int dy[] = {0, -1, 0, 1};
int last[MAXN];
short int mov[MAXN];
struct State{
    short int s[9];
    short int pos;
    int hash;
}ini;
queue<State> q;

int Hash(short int *s)
{
    int res=0;
    for(int i=0;i<8;i++)
    {
        int cnt=0;
        for(int j=i+1;j<9;j++)
            if(s[i]>s[j])
            cnt++;
        res +=cnt*fac[8-i];
    }
    return res;
}
int cal_pos(int pos,int i)
{
    int nx=pos/3+dx[i],ny=pos%3+dy[i];
    if(nx<0||nx>2||ny<0||ny>2)
        return -1;
    return nx*3+ny;
}
void BFS()
{
    State target;
    for(int i=0;i<9;i++)
        target.s[i] = i+1;
    target.pos=8;
    target.hash=0;
    has[0]=1;
    q.push(target);
    while(!q.empty())
    {
        State ha = q.front();
        q.pop();
        State tmp;
        for(int i=0;i<4;i++)
        {
            tmp.pos=cal_pos(ha.pos,i);
            if(tmp.pos<0)
                continue;
            for(int j=0;j<9;j++)
            {
                if(j==ha.pos)
                    tmp.s[j]=ha.s[tmp.pos];
                else
                    if(j==tmp.pos)
                        tmp.s[j]=ha.s[ha.pos];
                else tmp.s[j]=ha.s[j];
            }
            tmp.hash = Hash(tmp.s);
            if(has[tmp.hash])
                continue;
            q.push(tmp);
            has[tmp.hash]=1;
            last[tmp.hash]=ha.hash;
            mov[tmp.hash]=i;
        }
    }
}
 void print_path(int x)
 {
     if(x==0)
        return ;
     int i=mov[x];
     if(!i) printf("d");
     else if(i==1)
        printf("r");
     else if(i==2)
        printf("u");
     else
        printf("l");
     print_path(last[x]);
 }
 int main()
 {
     memset(has,0,sizeof(has));
     BFS();
     char tmp;
     while(cin>>tmp)
     {
         if(tmp!='x')
            ini.s[0]=tmp-'0';
         else
         {
             ini.s[0]=9;
             ini.pos=0;
         }
         for(int i=1;i<9;i++)
         {
             cin>>tmp;
             if(tmp=='x')
             {
                 ini.s[i]=9;
                 ini.pos=i;
             }
             else
                ini.s[i]=tmp-'0';

         }
         ini.hash=Hash(ini.s);
         if(!has[ini.hash])
            printf("unsolvable");
        else
            print_path(ini.hash);
        puts("");
              }
        return 0;
 }
复制代码

 

posted @   BlackSnow  阅读(178)  评论(1编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示