- UID
- 12226
- 帖子
- 6753
- 精华
- 10
- 性别
- 男
- 来自
- 上海
- 注册时间
- 2008-4-12
访问个人博客
|
107楼
发表于 2013-3-31 09:38
| 只看该作者
发一道昨天花了不少时间解决的排列组合题,当然思路是计算机科学的动态规划,纯组合学上的通用的closed from的答案目前还是没办法找到。
http://www.douban.com/note/269136472/
DP解决一道排列组合(湫秋系列故事——安排座位)
2013-03-30 20:33:28
http://acm.hdu.edu.cn/showproblem.php?pid=4532
湫秋系列故事——安排座位
Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 143 Accepted Submission(s): 38Problem Description
为了给腾讯公司找到更多优秀的人才,HR湫秋最近去某高校组织了一次针对该校所有系的聚会,邀请了每个系的一些优秀学生来参加。 作为组织者,湫秋要安排他们的座位。这并不是一件很简单的事情,因为只有一排位置,并且位置总数恰好等于参加聚会的人数。为了促进交流,两个来自相同系的同学不可以座位相邻。湫秋现在希望知道有多少种不同的合理安排座位的方法(任意两个合理的安排方法,只要有一个位置的同学不同,都被认为是不同的)。
Input
输入第一行为T,表示有T组测试数据。每组数据一个N开始,表示一共有多少个系。下面的一行包含N个整数Ai,表示每个系的到场人数。[Technical Specification]1. 1 <= T <= 472. 1 <= N, Ai <= 473. 1 <= Sum(Ai) <= 447
Output
对每组数据,先输出为第几组数据,然后输出结果。由于结果可能很大,输出对1,000,000,007 取余后的结果。
Sample Input
3 2 1 2 2 1 3 3 1 2 3
Sample Output
Case 1: 2 Case 2: 0 Case 3: 120
Source
2013腾讯编程马拉松复赛第一场(3月29日)
Recommend
liuyiding
我的思路:
这道题目是组合学的范畴,如果纯从组合角度考虑,利用容斥原理,也不是不能解决,只是会相当繁琐,布鲁迪《组合数学》第六章的习题17是一道类似的变例,当然这道题目与之还有区别,因为前者只需要同一个系学生的不全部连续排列即可,而这道题目需要同一系的学生两两分开。既然是算法题目,那就换种思路,用动态规划,DP来解决吧。
这里有n个系,按照最终人数由少到多排列为a1,a2,...,an
令N(c,b1,b2,...,bn)表示在{b1,b2,...,bn}人数情况下同系学生两两分隔的排列数,其中c=b1+b2+...+bn
那么现在来了第c+1位第x系的童鞋,不妨设x=n,现在的问题就是N(c+1,b1,b2,...,bn+1)如何递归推导出来?
首先任意一种原先c位已经排好序的序列中,共有c+1个空格可供我们的第c+1位童鞋排入,而他不能与其中的bn位系友相邻,因而只有c+1-2bn种位置。值得注意的是,这只是符合条件的一种情况,即新插入的同学插入到满意的位置,而该位置左右包括他本人在内,三位同学来自三个不同的系。
另外不能遗漏的一种情况是他插入到某个位置,该位置左右两位同学来自他不同的某个系。这种情况下,需要对n系之外的n-1个系逐一检查,如果这n-1个系中任何一个系有大于等于2个学生来参加聚会,则都应予以考虑。
综上,递归式如下
N(c+1,b1,b2,...,bn+1)=N(c,b1,b2,...,bn)*(c+1-2bn)+2[N(c-1,b1-1,b2,...,bn)+N(c-1,b1,b2-1,...,bn)+...+N(c-1,b1,b2,...,bn-1,bn)]
之所以第二种情况需要乘以2,是因为在考虑过程中将排在C同学前后的两位同系学生比如A和B,等价为A来考虑,但在具体情况下,A,C,B与B,C,A是两种不同情况。
很明显,边界条件为N(c,1,1,...,1)=c!,且N中任意一项若小于等于0,则N为0。
以N(6,1,2,3)来举例说明:
N(3,1,1,1)=3!=6,
N(4,1,2,1)=N(3,1,1,1)(4-2)=12=N(4,1,1,2)
需要说明的一点是,任意非递增序列的N数值上与递增序列相等,即N(4,1,2,1)=N(4,1,1,2),但要保持序列的对应关系。这点计算上的技巧接下来就会碰到。
N(5,1,2,2)=N(4,1,2,1)(5-2)+2*N(3,1,1,1)=12*3+2*6=48
N(6,1,2,3)=N(5,1,2,2)(6-2*2)+2*N(4,1,1,2)=48*2+2*12=120
OK,至此,整个dp的思路应该说的比较清楚了。具体code我就不写了,毕竟数年没有coding,生疏的不成样子,呵呵。
这两天还在着手写《具体数学》的读书笔记,Stay tuned! |
豆瓣http://www.douban.com/people/knowcraft
博客http://www.yantan.cc/blog/?12226
微博http://weibo.com/1862276280 |
|