关于几个数
来源:互联网 发布:h5万能表单系统源码 编辑:程序博客网 时间:2024/05/17 09:35
说这些数和公式之前,我想先说下一个非常重要的问题,也就是子问题,所谓子问题,无非就是问题实质和原问题一样,而规模小了一点而已,可能小了1,也可能小了一半,解决一个问题往往要解决它的子问题,然后通过子问题的值推到出原问题的答案,这也是动态规划的精髓之一。
1错排:
有n个人编号1到n,本来都站在各自的位置上,现在让他们站一排,每个人不能站在原来的位置上去,问有都少种排列方法?
现在我觉得我高中数学老师真水,做题碰到这种问题让我们列一遍。
我之所以前面说了子问题,是因为这里要用到,我假设f(n)表示n个人错排的方法数,那么f(n-1)就是n-1个人的错排方法数,那么假如n-1个人错排好了,我加一个人进去,显然我只能放在前n-1个位置的某个位置,假设我放在了位置k(1<=k<=n-1),那么k这个位置的人放哪里呢,他可以放在n,也可以不放在n,我们按照这样两种情况分,第一种,放在n,那么剩下n-2个人,只要他们也错排就好了,即f(n)的一部分值是由(n-1)*f(n-2)来的。第二种,不放在位置n,那么这种情况下还有多少种情况呢,其实我们在回过头考虑下,f(n)这函数的意义,就是说每个数不能放在原来的位置,也就是说,每个数都有一个位置是不能放的,这其实是等价的,那么对于刚才第二种情况,k不能放位置n,其余n-2个数不能放原来的位置,这就是f(n-1)!因此得到公式
f(n)=(n-1)*(f(n-1)+f(n-2))
至于初值,不说也罢,自己算下就好了。
我想说的一点是,这个公式牛逼的地方就是为什么想到按照放不放到n这个位置分开来。
2卡特兰数
给你n个左括号和n个右括号,要求把他们排成一排,要保证每个左括号都有一个在它右边右括号和它匹配,问你有多少种排列方法:
我感觉这里有两种意思,算是意味着有两种解题思路吧
首先,我们设f(n)为2*n括号的排列方法数,那么第一个括号肯定是左括号,它可以和某个右括号匹配,但是非常重要的一点是假如第一个和第K个括号匹配(2<=k<=2*n),那么k必须是偶数,否则,第一个到第k个直接之间(不包括1和k)存在了奇数个符号,肯定满足不了匹配,那么根据k的取值切开后,我们会发现2到k-1也是合法的字符串,k+1到2*n之间也是合法的,才能保证总体是合法的,枚举k后有:
f(n)=f(0)*f(n-1)+f(1)*f(n-2)+.....+f(n-2)*f(1)+f(n-1)*f(0),其中f(0)=1
那么我们是可以在O(n*n)时间内可以把f(n)求出来的。
不过其实这个问题还有另外一层意思 ,那就是对于任意前k个长度的括号串,必须保证左括号的个数大于等于右括号个数。否则右括号比左括号多,那么之后的n-k的括号,左括号比右括号多,是无论如何都满足不了任意一个左括号能和一个右括号匹配的。按照这种思路有一种做法是用所有的排列数,减去非法的字符排列数,不过比较复杂,这里略过。
阿里曾有一道笔试题,给你2*n个人,让他们站成2排,每排n人,必须保证,左边的人比后面的人矮,前面的人比后面的人矮,问你有多少种站法,本题的答案据说是卡特兰数,解释起来比较复杂, 大家可以好好思考下。
3斯特林数:
斯特林数有2类:首先说一下第二类斯特林数,给你n物品和一个数k,求把这n个物品分成k个非空集合的方法数。
我觉得这整个问题真的扯到了动态规划,设dp[i][j]表示i个物品分成j个非空集合的方法数,那么整个问题可以由2种状态转移过来,第一,就是第i个物品自己为一类,那么问题转化成了dp[i-1][j-1],第二,第i个物品是加到j类中的某一类的,那么由dp[i-][j]*j,所以有方程:
dp[i][j]=dp[i-1][j-1]+j*dp[i-1][j]
注意几个初值就能解决整个问题了。
第二类斯特林数和第一类的区别是,第二类分完类算是完成任务了,但是第一类还有一个轮换过程,就是它考虑了顺序。第一类斯特林数是指将n个物品分成k个非空集合的方法数(集合中有相同的物品但是不同的轮换算不同分法)。
这里说一下,轮换,比如好4个物品围成一个圈,ABCD 和BCDA,CDAB,DABC是相同的轮换,其他的4个物品的排列则都不是。所以第一类斯特林数是大于等于第二类,因为第一类在相同的物品下,还有一个排列顺序,而第二类并不考虑顺序。接下来来看方程。
和第一类类似的是,dp[i][j]也有一个状态是dp[i-1][j-1],此时第i个物品自己为一类,所以没有顺序而言,但是对于dp[i-1][j]就是说,我们将第i个物品放到j个类中去,就算是同一类根据不同的位置也算不同的方法,到底有多少种呢。答案是i-1(这个i-1可能不是那么好想),因为插入到物品中间都是不同的情况,所以有方程
dp[i][j]=dp[i-1][j-1]+(i-1)*dp[i-1][j]
关于这种排列组合题,个人觉得多思考练习下逻辑思维能力还是不错的,我觉得动态规划真的是个很神奇的东西,很多问题,都能用它解决。
- 关于几个数
- 关于回调函数的几个例子
- 关于回调函数的几个例子
- 关于回调函数的几个例子
- 股票中关于股份数的几个基本概念
- 任意排序几个数
- 几个数中的最小值
- 十几个数相加
- 几个连续数相加
- 关于连续的几个数中有一个数缺失并一次遍历找出的问题
- 判断几个数是否是水仙花数
- 给定几个数,求最大值
- 给定几个数,进行排序
- jquery 实现几个数相加
- 任意几个数大小排序
- 定点数的几个知识点
- 输入几个数逆序输出
- 求几个数的平均数
- Ext3.2.2 分页工具条如何隐藏刷新按钮
- hdu——1114——Piggy-Bank
- 使用readAsDataURL方法预览图片
- centOS服务器 netstat命令 查看TCP连接数信息(转)
- JAVA 注解验证字段(例子)
- 关于几个数
- java操作mongodb的几种方法
- ExtJS4.2 TreeGrid 的用法
- 白帽子——安全漏洞奖励网站收集
- 数据挖掘--Apriori算法实现
- 三星I9100/I91000G升级到安卓4.0的方法
- 11个惊人的CSS3和jQuery供电教程
- 推荐13款优秀的Twitter Bootstrap JavaScript插件
- redis的安装