• [复习资料][随想]如何枚举一个排列


    [随想]如何枚举一个排列

    感觉最近博客里啥也没有写了,赶紧来写个东西让博客看起来没有那么冷清(大雾

    有这样一类问题,需要你去枚举大小为 (n) 的全排列,此时可以从下面几种方法去考虑:

    1. “直接枚举”。枚举每个位置选的是哪个数,或者枚举每个数放在哪个位置。
    2. “插入法枚举”。从左到右考虑每个位置选择的数在前缀的排名,类似在前面排好序的所有数中插入一个数,或者从小到大枚举每个数插在的相对位置。
    3. “状压枚举”。从左到右考虑每个位置,状压已经使用过的所有数。
    4. “置换枚举/划分数枚举”。将排列看做是一个置换,此时可以通过枚举划分数来枚举每个置换的大小,如果已经知道每个置换的大小分别是 (a_1,a_2,dots,a_k(sum_{i=1}^ka_i=n)) ,大小为 (i) 的置换个数为 (b_i) ,那么置换大小恰好这么多的排列个数是 (frac{n!}{prod_{i=1}^ka_iprod_{i=1}^nb_i!})
    5. “笛卡尔树枚举”。枚举笛卡尔树上面每个点的父亲编号,或者枚举笛卡尔树上每个点的儿子编号,需要注意的是儿子是有顺序的(有左右儿子之分)。
    6. “多叉树枚举”。对于一个排列 (p) ,如果规定 (i) 的父亲节点是 (max {jmid j<iland p_j<p_i}igcap {0}) ,并且规定一个节点的儿子的顺序是按位置从小到大,那么就可以给这个排列构建出一棵儿子有顺序根为 (0) 的树,并且不难发现这样的树和排列是一一对应的,这棵树按儿子顺序 dfs 得到的 dfs 序恰好是排列 (p) ,并且这棵树满足一个点的编号要比排名比它小的兄弟和它的父亲大。

    对于上述的第 4 点的排列个数的解释,首先假设置换是有标号的,那么方案数就是:

    [{nchoose a_1,a_2,dots,a_k}prod_{i=1}^k(a_i-1)!=frac{n!}{prod_{i=1}^ka_i} ]

    但是置换是没有标号的,所以方案数是:

    [frac{n!}{prod_{i=1}^ka_iprod_{i=1}^nb_i!} ]

    对于第 6 点,构建出来的树其实还有一种构造方法,就是对于每个 (i(1le ile n)) ,给 (i)([0,i-1]) 中选择一个父亲,并且规定儿子顺序(这里儿子顺序是按编号从大到小)后得到的树,并且构建出来得到的树“多叉转二叉”后其实就是笛卡尔树。

    当然可能还会有其他枚举方法,我见到了大概(?)会放上来。

  • 相关阅读:
    MS SQLSERVER 第三天
    MS SQLSERVER 第二天
    今天开始我的 MSSQLSERVER 之旅
    从今天开始就正式我的博客之旅
    mac 本地搭建mybatisGenerator代码生成环境
    idea中git远程版本回退
    Junit调试解决本地多线程异步调用
    Lambda表达式总结
    JDK8函数式编程之Stream API
    MySql分页查询慢的解决方案
  • 原文地址:https://www.cnblogs.com/lsq147/p/14026411.html
Copyright © 2020-2023  润新知