• 八数码问题(九宫格重排) 利用康托展开 判重


    问题 E: [蓝桥杯][历届试题]九宫重排

    时间限制: 1Sec 内存限制: 128MB 提交: 69 解决: 17

    题目描述

    如下面第一个图的九宫格中,放着  1~8  的数字卡片,还有一个格子空着。与空格子相邻的格子中的卡片可以移动到空格中。经过若干次移动,可以形成第二个图所示的局面。

    我们把第一个图的局面记为:12345678. 
    把第二个图的局面记为:123.46758 
    显然是按从上到下,从左到右的顺序记录数字,空格记为句点。 
    本题目的任务是已知九宫的初态和终态,求最少经过多少步的移动可以到达。如果无论多少步都无法到达,则输出-1。

    输入

    输入第一行包含九宫的初态,第二行包含九宫的终态。 

    输出

    输出最少的步数,如果不存在方案,则输出-1。

    样例输入

    12345678. 
    123.46758 

    样例输出

    3
    #include<bits/stdc++.h>
    using namespace std;
    string s,d;
    bool vis[400000];
    int FAC[11];
    void init()
    {
        FAC[0]=1;
        for(int i=1;i<=10;i++)FAC[i]=FAC[i-1]*i;
    }
    int cantor(string a, int n)
    {
        int x = 0;
        for (int i = 0; i < n; ++i) {
            int smaller = 0;  // 在当前位之后小于其的个数
            for (int j = i + 1; j < n; ++j) {
                if (a[j] < a[i])
                    smaller++;
            }
            x += FAC[n - i - 1] * smaller; // 康托展开累加
        }
        return x+1;  // 康托展开值
    }
    int ans=-1;
    void bfs()
    {
        int dx[4]={1,0,-1,0};
        int dy[4]={0,1,0,-1};
        queue<string>q;
        string t=s;
        q.push(t);
        q.push("");
        vis[cantor(t,9)]=1;
        int depth=0;int x,y;int x2,y2;int newpos;
        while(!q.empty())
        {
            t=q.front();q.pop();
            if(t==""){depth++;q.push("");continue;}
            if(t==d){ans=depth;break;}
            else
            {
                int pos=0;
                while(t[pos]!='0')pos++;
                pos++;
                x=(pos+2)/3;
                y=(pos-1)%3+1;
                for(int i=0;i<4;i++)
                {
                    x2=x+dx[i];y2=y+dy[i];
                    if(x2<1||x2>3||y2<1||y2>3)continue;
                    newpos=(x2-1)*3+y2;
                    swap(t[pos-1],t[newpos-1]);
                    if(!vis[cantor(t,9)]){q.push(t);vis[cantor(t,9)]=1;}
                    swap(t[pos-1],t[newpos-1]);
                }
            }
        }
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        init();
        cin>>s>>d;
        for(int i=0;i<9;i++)if(s[i]=='.')s[i]='0';
        for(int i=0;i<9;i++)if(d[i]=='.')d[i]='0';
        bfs();
        cout<<ans<<endl;
        return 0;
    }
  • 相关阅读:
    MFC中DoDataExchange()的作用
    图片下面出现空白像素的问题解决
    nginx 的 autoindex on首页不显示的问题 按照下面几行要写上不然不行
    配置 PHP 的 Session 存储到 Redis
    redis4安装
    jumpserver安装
    mysql命令参数详解
    定制LNMP的RPM包
    NTP原理
    内网环境NTP服务及时间同步(CentOS6.x)配置和部署
  • 原文地址:https://www.cnblogs.com/linruier/p/9485157.html
Copyright © 2020-2023  润新知