如果给定集合L={1,2,3,...,N}
和整数k
,是否可以有效地计算大小为k
的“非相邻”子集的数量?如果S
中的x
S
x-1
x+1
,则S
中的L={1,2,3,4}
不属于k=2
。
例如,对于{1,3},{1,4},{2,4}
和k=3
,答案是3,因为我们有
{{1}}。对于{{1}},答案为零。
一种方法是生成所有大小为2的非相邻子集,然后尝试所有可能的联合(因为非相邻集合具有其所有子集都不相邻的属性),但这让我非常感兴趣浪费,可能有一个甜美优雅的高效解决方案。
答案 0 :(得分:1)
以这种方式思考:如果您知道集合L'={1, 2, 3, ..., N - 1}
的答案是什么,您是否可以使用该信息为集合L
构建答案?
我们的想法是,当您向N
添加L'
时,新解决方案由L'
可用的所有子集以及L'
的每个元素的1个新子集组成。小于或等于N - 2*(k - 1)
,因此,如果L'
的解决方案的大小为V'
,则V
L
的解决方案将为V = V' + (N - 2*(k - 1))
}}
如果你再多做一点,你会发现解决方案可以表示为第一个N - 2k + 2
自然整数的总和。
关于小于或等于N - 2*(k - 1)
部分,添加的新数字N
将仅添加到最终数量小于或等于该表达式结果的子集,因为必须有{正在构建新子集中的{1}}个元素(包括数字k
本身,因此需要N
个)彼此相隔至少2个数字,这使得距离为{来自数字k - 1
的{1}},以及表达式。
答案 1 :(得分:1)
这可能与Win32的解决方案一样,但我不确定。所以我将它单独发布。
将S(n)作为大小为n的连续序列的非相邻子集的数量(即,S(n)是您正在寻找的解决方案)。
让我们计算S(n + 1),即我们在序列中添加元素时的值。当我们添加元素k时,我们增加该序列的非相邻子集的数量。我们可以将这些 new 子集分解为以下类别。
因此,当我们向序列中添加k时,新的非相邻子集的数量是1 + S(n-1)。换句话说,1 + S(n-1)= S(n + 1)-S(n)。我们可以重新排列这个公式得到S(n + 1)= 1 + S(n-1)+ S(n)。
递归解决方案不是很有用,所以我们可以尝试概括它。我不擅长这一步,但Wolfram|Alpha is,我们发现通用公式等于以下内容。
以下是一些示例数据点。
n | S(n)
0 | 0
1 | 1
2 | 2
3 | 4
4 | 7
5 | 12
6 | 20
7 | 33
8 | 54
9 | 88
答案 2 :(得分:0)
由S(m,n)
表示m
中大小为{1,...,n}
的非相邻子集的数量。以下是:
S(m,n) = S(m,n-1) + S(m-1,n-2)
因此,通过添加边界条件
,可以通过O(Nk)
中的DP解决它
S(1,n) = n
S(m,1) = I(m==1)
S(m,2) = 2*I(m==1)
其中I()
是指标函数。
答案 3 :(得分:0)
让:
S(n,k)
是大小为{1,...n}
的{{1}}的非相邻子集
显然,k
是一组大小为S(n-1,k)
的非相邻子集,它是k
的子集。
此外,S(n,k)
是一组大小为S(n-2,k-1)
的非相邻子集,这些子集中没有一个包含k-1
。因此,我们可以安全地将n-1
添加到每个子集中,以获取大小为{n}
的子集。由于它们不包含k
(n-1
唯一的相邻元素),因此它们也不相邻。
因此:
n
使用一些实数,让我们尝试解决S(n,k) = S(n-1,k) U ({n} X S(n-2,k-1))
。
S(6,3)
哪个符合你的答案。
现在,要计算数字:
让
中的元素数量S(6,3) = S(5,3) U ({6} X S(4,2)) S(5,3) = {1,3,5} # Only one solution S(4,2) = S(3,2) U ({4} X S(2,1)) S(3,2) = {1,3} # Only one solution S(2,1) = {1} {2} # All sets of 1 element are non-adjacent {4} X S(2,1) = {1,4} {2,4} # Add {4} to each S(4,2) = {1,3} {1,4} {2,4} {6} X S(4,2) = {1,3,6} {1,4,6} {2,4,6} S(6,3) = {1,3,5} {1,3,6} {1,4,6} {2,4,6}
为N(n,k)
然后:
S(n,k)
我尚未确定封闭形式,但这里有一些计算值:
N(n,k) = N(n-1,k) + N(n-2,k-1)