本系列文章目录
2009年9月刊《程序员》算法题之我见——思索之一
笔者业余时间喜欢研究一些算法,也经常的阅读各类计算机杂志并对其中的算法题研究考量一番
翻阅了2009年9月刊《程序员》,其中的一道算法题吸引了我。虽然至今还没有理解透,但是也小有心得。拿在这个和大家交流一番。
先把题目复述一遍。
如何为实习生安排座位
有道最近招聘了一批实习生,给他们安排座位时遇到一个有趣的问题。办公室有N排,每排有M个座位。为了方便实习生和全职员工更好的交流,安排座位时,我们不让任何2个实习生座位水平、竖直、或者对角线相邻。求满足安排方案的总数。
文章最后给了一个测试条件:M=15,N=150,每排4人,求方案总数。
文章给了3个解决方案。可惜本人愚笨,没有能力参悟,只有自己一个人抽丝剥茧,层层深入,期待有朝一日,能够理解透。
为了描述方便,一共有N排,每排M个座位,每排安排P个实习生
问题一,M=15,则P最大为多少?毫无疑问P最大为8人。
而且这8人只有一种安排法
如图
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
示意图,红色表示实习生
问题二,M=S,P最大为多少?
参照问题一,可知,当S为奇数时,P最大为(S+1)/2;当S为偶数时,P最大为S/2
问题三,M=15,N=1,P=4,安排方案总数?
用一个函数表示安排总数F(M,P),其中M为座位数,P为人数,返回的是方案总数
不难理解,本题就是计算F(15,4)
而且,F还满足递归,即
F(15,4)=F(13,3)+F(12,3)+F(11,3)……+F(1,3)
那么,很容易的,该函数马上就能用代码表示出来
Private Function F(ByVal M As Integer, ByVal P As Integer) As Integer
If P <= 0 OrElse M <= 0 Then Return 0
If P = 1 Then Return M
If P * 2 = M + 1 Then Return 1
If P * 2 > M + 1 Then Return 0
Dim i As Integer, S As Integer, tS As Integer
S = 0
For i = M - 2 To 1 Step -1
tS = F(i, P - 1)
If tS = 0 Then
Return S
Else
S += tS
End If
Next
Return S
End Function
经计算,F(15,4)=495,所以本问题的解为495
问题四,M=15,N=2,P=4,安排方案总数?
由问题三可知,每排的可能性有495种,是不是意味着两排就一定是4952种呢?很显然,不是的。因为这两排彼此之间还互相有影响。下面举两个例子
例子一:下面这个情况就不符合题意
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
示意图,红色表示实习生
例子二:下面这个情况就符合题意
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
示意图,红色表示实习生
可见,对于第一行的每种情况,第二行并不完全都符合,还得分情况考虑。如果执着于分情况考虑,未免工作量太大。
仔细观察例子二情况,突然发现如果将两排压缩为一排的话,正好是问题一的图。而例子一压缩为一排的话,就不是问题一的图。
于是,基于此,提出一个假设。
该问题的每一个解都能压缩成问题一的图,而本题的每一个不成立的解都压不成问题一的解。也就是说,把问题一的图中随机选出四个位置作为第一排的情况,则另外四个位置就是第二排的情况。
则本题的答案就很明了了,C(8,4)=70种,C表示组合函数,这里就不详细解释了。
问题五:M=15,N=150,P=4,求方案总数
这是一开始的测试情况。也是问题四的延伸。这样想,第一排的位置定下来的话,第二排就一种情况。这是问题四的解。同时,第三排也就一种情况,和第一排相同,第四排受第三排的影响,也是一种情况,和第二排相同。以此类推,本题的解就是问题四的解C(8,4)=70种。
暂且思考到这儿,先把测试的情况计算出来。这个思路对其他的情况有着参考的作用。日后再撰文,与大家交流。