zoukankan      html  css  js  c++  java
  • 八数码问题(九宫格重排) 利用康托展开 判重

    问题 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;
    }
  • 相关阅读:
    Tomcat Jboss,jetty,Apache WebLogic区别与比较(阿里面试)
    zookeeper 负载均衡 核心机制-实现原理 包含ZAB协议(滴滴,阿里面试)
    六大Web负载均衡原理与实现
    LVS(Linus Virtual Server):三种IP负载均衡方式比较+另三种Web负载均衡方式
    JTable动态刷新数据
    java当中的定时器的4种使用方式
    java如何判断编码是否是utf8编码
    Java多线程-线程的同步与锁
    java中需要用equals来判断两个字符串值是否相等
    libcurl使用easy模式阻塞卡死等问题的完美解决---超时设置
  • 原文地址:https://www.cnblogs.com/linruier/p/9485157.html
Copyright © 2011-2022 走看看