zoukankan      html  css  js  c++  java
  • 1449:【例题2】魔板

    1449:【例题2】魔板

    题解

            这道题是一道非常典型的BFS题目,BFS所面临的最大问题是判断重复。显然,如果每次判
    断重复都扫描一次队列,搜索的效率将非常低,会提高一个指数级,所以一般宽度搜索的判断重复
    都是运用数组来实现的,那么数组下标就需要用一个Hash函数来计算出来。

            本题Hash函数的设计:我们很容易想到将8个数字按顺时针顺序组合成8进制(每个数字都
    减1)的8位基数。但是,这里最大的八进制数76543210,转换成十进制数是16434824,也就是说要
    开大小为16434824的数组,如果题目强制空间限制,那么,数组的下标会越界
    这里我们引入康托展开,即将一个排列对应成它在全排列中的序数,这样就不会MIE了

            引入康托展开

     设step[ ]记步数;记 i 的父结点为prt[ i ] ; a[ i ]表示第i个序列采用哪种变换。

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<functional>
    #include<cstdlib>
    #include<utility> 
    
    using namespace std;
    
    int jc[10]={1,1,2,6,24,120,720,5040};
    int g,st,prt[50005],b[1000001]={0},step[50005];
    char a[50005];
    struct mb
    {
        int a[2][4];
    }start,goal,q[90001];
    
    int Turn(mb x)    //康托展开 
    {
        int i,j,res=0,t[8],s;
        for(i=0;i<4;i++) t[i]=x.a[0][i];  //构成序列 
        for(i=3;i>=0;i--) t[7-i]=x.a[1][i];
        for(i=0;i<8;i++)
        {
            s=0;
            for(j=i+1;j<=7;j++)
              if(t[j]<t[i])  s++;   //找后面小于t[i]的值 
            res+=jc[7-i]*s;
        }
        return res;
    }
        
    mb Change(int way,int num)       //三种操作 
        {
            mb temp;
            if(way==1)   //A
            {
                for(int i=0;i<4;i++) temp.a [0][i]=q[num].a [1][i];
                for(int i=0;i<4;i++) temp.a [1][i]=q[num].a [0][i];
                return temp;
            } 
            
            if(way==2)   //B
            {
                temp.a [0][0]=q[num].a [0][3];
                temp.a [1][0]=q[num].a [1][3];
                for(int i=1;i<4;i++) temp.a [0][i]=q[num].a [0][i-1];
                for(int i=1;i<4;i++) temp.a [1][i]=q[num].a [1][i-1];
                return temp;
            } 
            
            if(way==3)    //C
            {
                temp.a [0][0]=q[num].a [0][0];
                temp.a [0][3]=q[num].a [0][3];
                temp.a [1][0]=q[num].a [1][0];
                temp.a [1][3]=q[num].a [1][3];
                temp.a [0][1]=q[num].a [1][1];
                temp.a [0][2]=q[num].a [0][1];
                temp.a [1][2]=q[num].a [0][2];
                temp.a [1][1]=q[num].a [1][2];
                return temp;
            } 
        }
        
    void Print(int num)    //递归出结果 
        {
            if(num==1) return ;
            Print(prt[num]);
            cout<<a[num];
        }
        
    void Bfs()
        {
            int op=1,cl=1,i,t;   //op,cl记录操作数,op记变化前,cl记变化后
            mb temp;
            q[1]=start;
            step[1]=0;
            prt[1]=1;
            while(op<=cl)
            {
                for(i=1;i<=3;i++)   //三种变换
                {
                    temp=Change(i,op);
                    t=Turn(temp);
                    if(!b[t])     //未标记,入队
                    {
                        q[++cl]=temp;
                        step[cl]=step[op]+1;
                        b[t]=1;
                        prt[cl]=op;     //记录父节点,也就是上一步操作编号
                        a[cl]=char('A'+i-1);   //记录操作类型
                        if(t==g)
                        {
                            cout<<step[cl]<<endl;
                            Print(cl);
                            return;
                        }
                    }
                }
                
            op++;
            }
        
        }
        
     
    
    int main()
    {
        int i;
        for(i=0;i<4;i++) start.a [0][i]=i+1;     //初始化起始状态
        for(i=3;i>=0;i--) start.a [1][i]=8-i;
        st=Turn(start);    //标记起始状态
        b[st]=1;
        for(i=0;i<4;i++)
          cin>>goal.a [0][i];
        for(i=3;i>=0;i--)
          cin>>goal.a [1][i];
        g=Turn(goal);
        if(g==st)
        {
            cout<<0;
            return 0;
        }
        Bfs();
        return 0;
    }
  • 相关阅读:
    面板评分太低会算两次
    没有使用大漩涡传送门没有杀死大法师瓦格斯
    win10创建本地用户
    延迟着色
    GPU 优化总结
    UE4 减少APK包的大小
    UE4 性能优化方法(工具篇)
    Unreal Engine 4的常见Tips
    虚幻引擎4设置Visual Studio
    模型导入的单位问题
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/10992683.html
Copyright © 2011-2022 走看看