我正在尝试解决动态编程问题,部分问题涉及查找 一组'的排列数量。数字总计为数字' n'。 p数集中的每个数字应该在0到n之间。
例如,如果n = 4且p = 3,我有以下12种排列
{4,0,0},{0,4,0},{0,0,4}
{2,2,0},{2,0,2},{0,2,2}
{1,3,0},{1,0,3},{0,1,3}
{1,1,2},{1,2,1},{2,1,1}
我开始使用这种DP方法。
n(i,j) represents number of ways of representing n using i,j in p positions
我的基本情况是
n(i,0) = n(0,i) = p
(例如,p = 3位的n(4,0)为3,即{4,0,0},{0,4,0},0,0,4}
递归案例
n(i,j) = n(i,j-1)*n(i-1,j)
(例如:n(1,2)= n(1,1)* n(0,2)递归到n(1,0)* n(0,1)* 2)
我不确定我是否正朝着正确的方向前进,因为上述方法并没有引导我找到正确的答案。请指导我正确的方向。
答案 0 :(得分:6)
与我的评论相反,如果我们同时计算集合的数量和这些集合的排列,这个问题实际上更容易解决。
如果我们只需要计算而不是实际生成每个集合,我们可以直接使用一些简单的组合。让我们为我们的例子修复p = 3, n = 5
并想象我们有n = 5
个球:
o o o o o
现在问题相当于,有多少种方法可以将球分成3
组,每组可以有[0, 5]
个球?想象一下,如果我们有p - 1 = 2
棍棒,我们可以单独放置在任何地方:在所有五个球之前,在所有五个球之后,以及在任意两个球之间。例如:
| o o | o o o => (0, 2, 3)
o | | o o o o => (1, 0, 4)
o o o o | | o => (4, 0, 1)
注意问题是如何相同的?无论如何,我们可以放置那些棍棒,我们也可以将n
球分成p
组。请注意,我们只需要p - 1
个棍棒来生成p
个数字(第一个棍子之前的所有球是第一组,最后一个棍子之后的所有球是最后一组,两个棍子之间的任何球)是其他团体。)
所以现在我们的问题是我可以用多少种方式安排n
球和p - 1
棒?您可以将其视为拥有n + (p - 1)
个插槽,并且您只是选择球的n
点......其余的就是棒的位置。以这种方式思考它我们可以应用组合学的基本公式(它已经证明了使用公理和产品规则的公理规则......不确定我是否曾经见过证据):
(n + (p - 1)) Choose n = (n + (p - 1))! / n! / (p - 1)!
所以在我们的例子中,它是7! / 5! / 2! = 21
。你可以在你的例子中看到它是6! / 4! / 2! = 15
。您错过了一些排列(例如,{0, 3, 1}
)。
您也可以通过简单的递归方程式解决这个问题。基本上
`f(n, p) = Sum over i = 0 to n, f(n - i, p - 1)`
并记住f
的一些值。我们的想法是,您为集合S
的第一个成员选择值,然后下一个递归调用选择S
的下一个成员,依此类推。基本情况可能类似于f(0, p) = 1
和f(n, 0) = 0
,否则您可以使用递归情况。如果您实际上并不需要这些集合,那么封闭形式显然会更高效。