• P1379 八数码难题


    漂亮小姐姐单击就送:https://www.luogu.org/problemnew/show/P1379

    题目描述

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

    输入输出格式

    输入格式:

    输入初始状态,一行九个数字,空格用0表示

    输出格式:

    只有一行,该行只有一个数字,表示从初始状态到目标状态需要的最少移动次数(测试数据中无特殊无法到达目标状态数据)

    输入输出样例

    输入样例#1: 复制
    283104765
    
    输出样例#1: 复制
    4



    /*这道题一开始用的是map判重,TLE了俩点。然后改hash,全WA了,感觉我自己写hash选模数靠运气。
    然后不写hash了,写进制位,AC了,因为知道了前八位数后,第九位就能确定,所以只求前八位数的和就可以。 
    */
    
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<string> 
    #include<queue>
    using namespace std;
    
    int pos,x,y,ans;
    int sum;
    string s;
    char a[4][4];
    struct state    //记录搜索状态 
    {
        string s;    //字符串表状态 
        int step;    //到达这个状态需要几步 
    }now,temp;
    bool flag[88888888];    //八位数判重 
    queue<state> que;        //搜索用的队列 
    int cx[4]={-1,0,1,0};    //改方向用的数组 
    int cy[4]={0,1,0,-1};
    
    void mswap(char &a,char &b)        //手写swap 
    {
        char c;
        c=a;a=b;b=c;
        return;
    }
    
    string change()        //将图转化成字符串,顺便求前八位数的和 
    {
        sum=0;
        string s;
        for(int i=1;i<=3;i++)
        {
            for(int j=1;j<=3;j++)
            {
                s+=a[i][j];
                if(!(i==3&&j==3)) sum=sum*10+a[i][j]-'0';    //求前八位数 
            }
        }
        return s;
    }
    
    void bfs()
    {
        while(!que.empty())
        {
            pos=0;
            now=que.front();que.pop();
            for(int i=1;i<=3;i++)    //转化成一个3*3的矩阵 
            {
                for(int j=1;j<=3;j++)
                {
                    if(now.s[pos]=='0') x=i,y=j;
                    a[i][j]=now.s[pos++];
                }
            }
            for(int i=0;i<4;i++)    //上下左右四个方向找 
            {
                if(x+cx[i]>0&&x+cx[i]<4&&y+cy[i]>0&&y+cy[i]<4)
                {
                    mswap(a[x][y],a[x+cx[i]][y+cy[i]]);        //换位 
                    temp.s=change();    //将图转化成字符串,判重 
                    if(temp.s=="123804765")        //到达了目标状态,输出答案 
                    {
                        printf("%d",now.step+1);
                        return;
                    }
                    if(!flag[sum])        //当前状态没出现过,添加状态 
                    {
                        flag[sum]=1;
                        temp.step=now.step+1;
                        que.push(temp);
                    }
                    mswap(a[x][y],a[x+cx[i]][y+cy[i]]);        //再换回来 
                }
            }
        }
    }
    
    int main()
    {
        cin>>s;
        now.s=s;now.step=0;
        que.push(now);
        for(int i=0;i<8;i++)    //初始状态判重 
        {
            sum=sum*10+s[i]-'0';
        }
        flag[sum]=1;
        if(sum==12380476)
            puts("0");
        else
            bfs();
        return 0;
    }
    bfs+八维数组
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    int n,m,x,y,ans,maxdep;
    int cx[5]={1,-1,0,0};
    int cy[5]={0,0,-1,1};
    int gx[9]={0,1,1,1,2,3,3,3,2};
    int gy[9]={0,1,2,3,3,3,2,1,1};
    int map[4][4];
    
    int h()
    {
        int ans=0;
        for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
            if(map[i][j])
                ans+=abs(i-gx[map[i][j]])+abs(j-gy[map[i][j]]);
        return ans;
    }
    
    void dfs(int X,int Y,int dep)
    {
        int H=h();
        if(!H)
        {
            printf("%d",dep);
            exit(0);
        }
        if(dep==maxdep||H+dep>maxdep)
            return;
        for(int i=0;i<4;i++)
        {
            int x=X+cx[i];
            int y=Y+cy[i];
            if(x&&y&&x<4&&y<4)
            {
                swap(map[X][Y],map[x][y]);
                dfs(x,y,dep+1);
                swap(map[X][Y],map[x][y]);
            }
        }
    }
    
    char c;
    int main()
    {
        for(int i=1;i<=3;i++)
            for(int j=1;j<=3;j++)
            {
                cin>>c;
                map[i][j]=c^'0';
                if(!map[i][j])
                    x=i,y=j;
            }
        if(!h())
        {
            puts("0");
            return 0;
        }
        for(maxdep=1;;++maxdep)
        {
            dfs(x,y,0);
        }
    }
    和别人比起来好慢的IDA*
  • 相关阅读:
    Excel 小技能
    Socket,ServerSocket,WebSocket
    浅谈Java中的关键字
    线程 学习教程(一): Java中终止(销毁)线程的方法
    OpenGL — GLFW — 颜色
    解决PCL MLS : error LNK2019; error LNK2001 virtual MovingLeastSquares process performProcessing问题
    获取显示屏的个数和分辨率
    Window 显示鼠标的坐标
    OpenCV 鼠标手动绘制掩码图像
    Windows 8 64位系统 在VS2010 32位软件上 搭建 PCL点云库 开发环境
  • 原文地址:https://www.cnblogs.com/lovewhy/p/8717213.html
Copyright © 2020-2023  润新知