• 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;
    }
  • 相关阅读:
    spring mongodb查询
    spring mongodb分页,动态条件、字段查询
    js导航下拉菜单
    spring mongodb增删改查操作
    组件
    vue的基本指令
    远程连接MongoDB数据库
    webpack工具、Vue、react模块化
    layui
    anaconda使用,jupyter notebook的使用方法
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/9313064.html
Copyright © 2020-2023  润新知