zoukankan      html  css  js  c++  java
  • 2007年中山大学内部选拔赛第六试----九数码

    本题的题意是:给出一个包含数字1~9的排列的目标状态和一系列不同的操作,再给出一些起始状态,求出从起始状态达到目标状态所需要的最少操作数。

    首先这是一个九宫格,其实也就是求一个排列数,9!是所有的状态,即362880。

    而每一个排列 都对应着一个康托展开数,开辟一个ans数组,下标是康托展开数,存入从目标状态到起始状态所需要的最小步数即可。

    等到使用的时候直接进行查询,这样可以应对有很多输入的情况。

    为什么说是从目标状态到起始状态呢?因为从起始状态到目标状态和从目标状态到起始状态的最小步数是一样的啊。

    然后从目标状态123456789开始向所有状态广搜就可以了,每一次进入队列的对应状态都可以求出康托展开数,然后顺便通过now.step=pre.step+1求出步数即可。

    对于康拓展开,百度百科,那里面说的很清楚,我还趁此机会顺便修改了词条,开心。

    #include <stdio.h>
    #include <string.h> 
    
    const int MAXNODE = 362880;
    
    struct State {
        char d[9];
        short f;
    };
    
    int pow[] = {1, 2, 6, 24, 120, 720, 5040, 40320};
    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));
    
        head = -1;
        tail = 0;
        Q[0].f = 0;
        for (int i = 0; i < 9;i++)
            Q[0].d[i] = i + 1;
        ans[State2I(Q[0])] = 0;
        while (head++<tail) {
            State &p = Q[head], q;
            q.f = p.f + 1;
            for (int i = 0; i < 4;i++) {
                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) {
            p.d[0] = x;
            for (int i = 1; i < 9;i++) {
                scanf("%d",&x);
                p.d[i] = x;
            }
            printf("%d
    ", ans[State2I(p)]);
        }
    }
    
    int main()
    {
        PreCom();
        work();
        return 0;
    }
  • 相关阅读:
    sql 随机获取100条数据
    NPOI导出信息
    JavaScript打印页面
    生僻字在页面上不显示(䶮)
    C# 下载文件并使用指定名称展示
    layui 表格列编辑获取编辑前的值然后重新赋值,并通过键盘控制编辑位置
    C# 网络图片转base64
    C# WebApi debug模式下编译没有问题,切换到release模式下编译就有异常,但是依旧能生成成功,再切回到debug模式也会报错,也可以生成成功
    HTTP/2
    Class的继承
  • 原文地址:https://www.cnblogs.com/xyqxyq/p/10211380.html
Copyright © 2011-2022 走看看