给定具有n个元素的集合C(允许重复)和具有n
个的分区P.
P = {i1,i2,... / i1 + i2 + ... = n}
在大小为i1,i2,......的子集中有多少不同的C分解?
示例:
C = {2 2 2 3}
P = {2 2}
C = {2 2} U {2 3}
P = {1 1 2}
C = {2} U {2} U {2 3}
C = {2} U {3} U {2 2}
P = {1 3}
C = {2} U {2 2 3}
C = {3} U {2 2 2}
我有一个解决方案,但是当C有十几个元素时效率很低 提前谢谢你 菲利普
答案 0 :(得分:1)
分解顺序对你来说无关紧要的事实使得它变得更加困难。也就是说,您正在查看{2 2} U {2 3}
与{2 3} U {2 2}
相同。我的算法仍然比你的算法好,但不是很好。
让我以一个现实复杂的例子开始吧。我们的设置为A B C D E F F F F G G G G
。分区将为1 1 1 1 2 2 5
。
我的第一个简化是用数据结构[[2, 4], [5, 1]]
来表示我们关注的信息,意味着2个元素重复4次,5个重复一次。
我的第二个明显的复杂因素是用[[5, 1, 1], [2, 2, 1], [4, 1, 1]
表示分区。这种模式可能并不明显。每个条目的格式为[size, count, frequency]
。因此,2个大小为2的分区的一个不同实例变为[2, 2, 1]
。我们还没有使用频率,但它正在计算相同大小和共性的可区分堆。
现在我们要按如下方式递归。我们将采用最常见的元素,并找到使用它的所有方法。因此,在我们的例子中,我们采用4号堆中的一个,发现我们可以按如下方式划分它,按字典顺序重新排列每个剩余的分区策略:
[4]
离开[[1, 1, 1], [2, 2, 1], [1, 4, 1]] = [[2, 2, 1], [1, 4, 1], [1, 1, 1]]
。[3, [1, 0], 0]
离开[[2, 1, 1], [1, 1, 1], [2, 1, 1], [1, 4, 1]] = [[2, 1, 2], [1, 4, 1], [1, 1, 1]
。 (请注意,我们现在正在使用频率。)[3, 0, 1]
离开[[2, 1, 1], [2, 2, 1], [0, 1, 1], [1, 3, 1]] = [[2, 2, 1], [2, 1, 1], [1, 3, 1]]
[2, [2, 0], 0]
离开[[3, 1, 1], [0, 1, 1], [2, 1, 1], [1, 4, 1]] = [[3, 1, 1], [2, 1, 1], [1, 4, 1]]
[2, [1, 1], 0]
离开[[3, 1, 1], [1, 2, 1], [1, 4, 1]] = [[3, 1, 1], [1, 4, 1], [1, 2, 1]]
[2, [1, 0], [1]]
离开[[3, 1, 1], [1, 1, 1], [2, 1, 1], [0, 1, 1], [1, 3, 1]] = [[3, 1, 1], [2, 1, 1], [1, 4, 1], [1, 1, 1]]
[2, 0, [1, 1]]
离开`[[3,1,1],[2,2,1],[0,2,1],[1,2,1]] = [[3,1, 1],[2,2,1],[1,2,1]] 1 [1, [2, 1]]
离开[[4, 1, 1], [0, 1, 1], [1, 1, 1], [1, 4, 1]] = [[4, 1, 1], [1, 4, 1], [1, 1, 1]]
[1, [2, 0], [1]]
离开[[4, 1, 1], [0, 1, 1], [2, 1, 1], [0, 1, 1], [1, 3, 1]] = [[4, 1, 1], [2, 1, 1], [1, 3, 1]]
[1, [1, 0], [1, 1]]
离开[[4, 1, 1], [1, 1, 1], [2, 1, 1], [0, 2, 1], [1, 2, 1]] = [[4, 1, 1], [2, 1, 1], [1, 2, 1], [1, 1, 1]]
[1, 0, [1, 1, 1]]
离开[[4, 1, 1], [2, 2, 1], [0, 3, 1], [1, 1, 1]] = [[4, 1, 1], [2, 2, 1], [1, 1, 1]]
[0, [2, 2]]
离开[[5, 1, 1], [0, 2, 1], [1, 4, 1]] = [[5, 1, 1], [1, 4, 1]]
[0, [2, 1], [1]]
离开[[5, 1, 1], [0, 1, 1], [1, 1, 1], [0, 1, 1], [1, 3, 1]] = [[5, 1, 1], [1, 3, 1], [1, 1, 1]]
[0, [2, 0], [1, 1]]
离开[[5, 1, 1], [0, 2, 1], [2, 1, 1], [0, 2, 1], [1, 2, 1]] = [[5, 1, 1], [2, 1, 1], [1, 2, 1]]
[0, [1, 1], [1, 1]]
离开[[5, 1, 1], [1, 2, 1], [0, 2, 1], [1, 2, 1]] = [[5, 1, 1,], [1, 2, 2]]
[0, [1, 0], [1, 1, 1]]
离开[[5, 1, 1], [1, 1, 1], [2, 1, 1], [0, 3, 1], [1, 1, 1]] = [[5, 1, 1], [2, 1, 1], [1, 1, 2]]
[0, 0, [1, 1, 1, 1]]
离开[[5, 1, 1], [2, 2, 1], [0, 4, 1]] = [[5, 1, 1], [2, 2, 1]]
现在可以递归地解决每个子问题。这可能感觉我们正在构建所有这些,但我们不是,因为我们memoize递归步骤。事实证明,前两组8人可以通过很多方式结束相同的5次剩余。通过记忆,我们不需要反复重新计算这些解决方案。
那就是说,我们会做得更好。 12个元素的组不应该成为问题。但我们并没有更好地 。如果它开始在30个左右的元素组中分解,并且有一组有趣的分区,我不会感到惊讶。 (我没有对它进行编码。它可能在30处可以正常,在50处可以分解。我不知道它会在哪里发生故障。但是考虑到你在一些分区上进行迭代,在一些相当小的点上它< em>将分解。)
答案 1 :(得分:0)
所有分区都可以分两个阶段找到。
首先:从P
创建新的有序分区n,P_S={P_i1, P_i2, ..., P_ip}
,总结相同的i。
P = {1, 1, 1, 1, 2, 2, 5}
P_S = (4, 4, 5)
针对{C_i1, C_i2, ..., C_ip}
制作C
分区P_S
。请注意,C_ix
是多集的,如C
。它按照最终分区的大小将C划分为多个集合。
第二:针对每个{C_i1, C_i2, ..., C_ip}
和每个ix, x={1,2,...,p}
查找C_ix
到t
的分区数(ix's
中P
的数量)设置ix
个元素。拨打此号码N(C_ix,ix,t)
。
分区总数为:
sum by all {C_i1, C_i2, ..., C_ip} ( product N(C_ix,ix,t) ix={1,2,...,p} )
第一部分可以递归地完成,非常简单。第二是更复杂。使用M
元素将多集n
划分为k
部分与使用M
中的元素查找所有部分排序列表相同。部分订单列表的类型为:
a_1_1, a_1_2, ..., a_1_k, a_2_1, a_2_2, ..., a_2_k, ....
a_i_x <= a_i_y
x < y
和(a_x_1, a_x_2, ..., a_x_k) lexicographic <= (a_y_1, a_y_2, ..., a_y_k)
x < y
的位置。使用这两个条件,可以递归地从N(C_ix,ix,t)
创建所有分区。
对于某些情况,N(C_ix,ix,t)
很容易计算。将|C_ix|
定义为多集C_ix
中不同元素的数量。
if t = 1 than 1
if |C_ix| = 1 than 1
if |C_ix| = 2 than (let m=minimal number of occurrences of elements in C_ix) floor(m/2) + 1
in general if |C_ix| = 2 than partition of m in numbers <= t.