zoukankan      html  css  js  c++  java
  • 哈尔滨理工大学2016新生赛E题

    多组数据,每组测试数据输入9个整数,为1-9的一个全排列。初始状态会被描述为

    1 2 3 4 5 6 7 8 9

    Output

    输出所需要的最小移动步数。

    Sample Input

    1 2 3 4 5 6 7 8 9

    9 8 7 6 5 4 3 2 1 

    Sample Output

    0

    12

    将每个排列利用康托展开压缩为一个整数,采用广度优先搜索的方式不停的搜索直到得到目标状态即可。

    #include <stdio.h>
    #include <string.h>
    
    const int MAXNODE=362880;            //最大状态数
    
    struct State {
        char d[9];                        //状态中的9个字符
        short f;                            //这个状态到达目标状态的最少操作数
    };
    //pow[i]表示(i+1)!
    int pow[]={1,2,6,24,120,720,5040,40320};
    //4种不同的操作的逆操作的置换顺序
    int rot[4][9]={{1,4,2,0,3,5,6,7,8},{0,2,5,3,1,4,6,7,8},{0,1,2,4,7,5,3,6,8},{0,1,2,3,5,8,6,4,7}};
    
    short ans[MAXNODE];                    //到达每个状态的结果
    int head,tail;                        //广度优先搜索中使用的队列头与尾
    State Q[MAXNODE];                    //广度优先搜索中使用的队列
    
    //用康托展开把一个状态变换成一个整数
    int State2I(State &p)
    {
        int ret=0;
        for(int i=0;i<8;i++)            //使用康托展开的公式
            for(int j=i+1;j<9;j++) if(p.d[i]>p.d[j]) ret+=pow[7-i];
        return ret;
    }
    
    //预处理所有状态到达目标状态的最少操作数
    void PreCom()
    {
        memset(ans,255,sizeof(ans));    //清空数组为-1
        
        head=-1,tail=0;                    //初始化队列头尾
        Q[0].f=0;                            //初始状态操作数为0
        for(int i=0;i<9;i++) Q[0].d[i]=i+1;//初始化初始状态
        ans[State2I(Q[0])]=0;            //初始状态的答案为0
    
        while(head++<tail) {            //运算直到队列为空
            State &p=Q[head],q;
            q.f=p.f+1;                    //经过一次操作
            for(int i=0;i<4;i++) {        //枚举4种不同的操作
                //按操作的置换顺序变换
                for(int j=0;j<9;j++) q.d[j]=p.d[rot[i][j]];
                int u=State2I(q);        //得到新状态的康托展开值
                if(ans[u]<0) {            //这个状态并未被扩展
                    ans[u]=q.f;            //更新状态答案
                    Q[++tail]=q;            //新状态放到队列末端
                }
            }        
        }
    }
    //处理输入和输出
    void Work()
    {
        State p;
        int x;
    
        while(scanf("%d",&x)==1) {        //输入整数x直到文件结束
            p.d[0]=x;
            for(int i=1;i<9;i++) {
                scanf("%d",&x);            //共输入9个数字
                p.d[i]=x;
            }
            printf("%d
    ",ans[State2I(p)]);//直接查表得到结果并输出
        }
    }
    
    int main()
    {
        PreCom();                            //预处理
        Work();                            //处理输入输出
        return 0;
    }
  • 相关阅读:
    使用grpc C++功能
    华为任正非访谈
    苹果产品
    异步编程
    基于磁盘存储
    spring 应用
    java简单框架设计
    消息队列架构
    03 java 基础:注释 关键字 标识符 JShell
    02 java 基础:java 文件名与类名关系 CLASSPATH
  • 原文地址:https://www.cnblogs.com/xingkongyihao/p/6105745.html
Copyright © 2011-2022 走看看