• 信件错排问题分析(动态规划)


    问题描述

    有 N 个信件和信箱,每封信件对应一个正确信箱位置。现在它们被打乱,求错误装信方式的数量。保证每一封信都装在错误的位置。

    思路

    抽象成动态规划问题

    定义一个数组dp[]存储错误方式数量。dp[i]表示,有i封信、i个信箱情况下的错误装信方法总数。

    转移方程建立

    对于第N封信而言,假设其装在了第 K 个信箱中,对于第 K 封信,有两种情况,(1)信件 K 装在信箱 N 中;(2)信件 K 未被装在信箱 N 中。

    1. 信件K装在信箱N中

    如下图所示:
    image
    我们不看 K 和 N 两对信件和信箱,只关注剩下 N-2 对信件和信箱,有 dp[N-2] 种错误装信方法。同时, K 的取值范围: 1~N-1 ,因此共有 (N-1)*dp[N-2] 种错误装信方法。

    2. 信件 K 未被装在信箱 N 中

    如下图所示:
    image

    先给出结果,该情况的错误装信方法有 (N-1)*dp[N-1] 种。这个 dp[N-1] 是如何得出来,我思考了良久。

    我们把问题重新描述一下,思路就会清晰很多。事实上,对于信件 i 来说,信箱 i 是它的“专属信箱”,每个信件都不能放入自己的专属信箱,对于n 个信件而言,都需要找其它 n-1 个信箱放入,其错排方法数为 dp[n] 。

    问题的症结在于,对于上图中的信件 K 来说,其专属信箱,即 K 信箱已经被占用。

    但是,我们可以把信箱 N 当做信件 K 的“专属信箱”,因为本情况下,信件 K 也不能放入信箱 N 。所以可以理解成求 N-1 封信件和 N-1 个信箱(除去信件 N)之间的错排数量问题。所以得到 dp[N-1]。

    同理 K 的取值范围: 1~N-1 ,因此共有 (N-1)*dp[N-1] 种错误装信方法。

    综上,状态转移方程
    image

    代码

        /**
         * 动态规划-信件错排问题
         */
        private int MailMisalignment(int n){
            if(n==0) return 0;
            if(n==1) return 0;
            int[] dp = new int[n];
            dp[0] = 0;
            dp[1] = 1;
            for(int i=2;i<n;++i){
                dp[i] = (i-1)*dp[i-2] + (i-1)*dp[i-1];
            }
            return dp[n-1];
        }
    
  • 相关阅读:
    `cd -`
    .git文件夹过大的解决方法
    避免对函数参数的修改
    2020年10月 修改Ant Design Pro底部版权信息的方法
    度目-人脸应用套件 文档中的坑
    "A little like that j-thing"
    Linux安装MySQL后设置密码
    append对len和cap的影响
    s := []int{0, 1, 2, 3, 8: 100}
    Python学习笔记
  • 原文地址:https://www.cnblogs.com/buptleida/p/13229545.html
Copyright © 2020-2023  润新知