zoukankan      html  css  js  c++  java
  • SSLZYC 洛谷P1379 八数码难题

    题目大意:
    在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字。棋盘中留有一个空格,空格用0来表示。空格周围的棋子可以移到空格中。要求解的问题是:给出一种初始布局和目标布局(为了使题目简单,设目标状态为123804765),找到一种最少步骤的移动方法,实现从初始布局到目标布局的转变。


    思路:

    BFS+HASH

    用bfs求出正确答案,hash判重。
    真不知道为什么洛谷评为 提高+/省选- 难度


    代码:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const int dx[5]={0,0,0,-1,1};
    const int dy[5]={0,1,-1,0,0};
    const int k=362881;
    int x,y,ok,sum,head,tail,q;
    int state[k][4][4],father[k],a[4][4],ha[k];
    
    int locate(int x)  //哈希判重
    {
        int y=0;
        for (int i=1;i<=3;i++)
         for (int j=1;j<=3;j++)
          y=y*10+state[x][i][j];
        int t=y%k;
        int i=0;
        while (i<k&&ha[(t+i)%k]!=0&&ha[(t+i)%k]!=y) i++;
        if (ha[(t+i)%k]==0)
        {
            ha[(t+i)%k]=y;
            return 0;
        }
        else return 1;
    }
    
    void print(int x)  //输出
    {
        if (father[x]==0) return;
        print(father[x]);
        sum++;
        return;
    }
    
    void bfs()  //广搜
    {
        father[1]=0;
        head=0;
        tail=1;
        do
        {
            head++;
            for (int i=1;i<=4;i++)
            {
                for (int j=1;j<=3;j++)
                 for (int k=1;k<=3;k++)
                 {
                    if (state[head][j][k]==0)
                    {
                        x=j;
                        y=k;
                        break;
                    }
                 } 
                if (x+dx[i]<1||x+dx[i]>3||y+dy[i]<1||y+dy[i]>3) 
                                                   continue;  //出界
                tail++;
                father[tail]=head;
                for (int j=1;j<=3;j++)
                 for (int k=1;k<=3;k++)
                  state[tail][j][k]=state[head][j][k];
                state[tail][x][y]=state[tail][x+dx[i]][y+dy[i]];
                state[tail][x+dx[i]][y+dy[i]]=0;  //交换(移动)
                if (locate(tail)==1) tail--;  //判重
                ok=1;
                for (int j=1;j<=3;j++)
                 for (int k=1;k<=3;k++)
                  if (state[tail][j][k]!=a[j][k])
                  {
                      ok=0;
                      break;
                  }
                if (ok==1)  //达到目标
                {
                    print(tail);  //输出
                    tail=-1;
                    return;
                }
            }
        }    
        while(head<tail);
    }
    
    int main()
    {
        a[1][1]=1;a[1][2]=2;a[1][3]=3;
        a[2][1]=8;a[2][2]=0;a[2][3]=4;
        a[3][1]=7;a[3][2]=6;a[3][3]=5;  //初始化
        for (int i=1;i<=3;i++)
         for (int j=1;j<=3;j++)
          scanf("%1d",&state[1][i][j]);
        for (int i=1;i<=3;i++)
         for (int j=1;j<=3;j++)
         {   
             q++;
             if (q==9) q=0;
             if (state[1][i][j]!=q) break;
             if (q==0)   //特判
             {
                 puts("0");
                 return 0;
             }
         } 
         locate(1);   //保存初始情况
         bfs();
         printf("%d\n",sum);
         return 0;
    }
  • 相关阅读:
    CodeForces 659F Polycarp and Hay
    CodeForces 713C Sonya and Problem Wihtout a Legend
    CodeForces 712D Memory and Scores
    CodeForces 689E Mike and Geometry Problem
    CodeForces 675D Tree Construction
    CodeForces 671A Recycling Bottles
    CodeForces 667C Reberland Linguistics
    CodeForces 672D Robin Hood
    CodeForces 675E Trains and Statistic
    CodeForces 676D Theseus and labyrinth
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313064.html
Copyright © 2011-2022 走看看