Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 具有给定约束的分区数_Algorithm_Partitioning_Combinatorics - Fatal编程技术网

Algorithm 具有给定约束的分区数

Algorithm 具有给定约束的分区数,algorithm,partitioning,combinatorics,Algorithm,Partitioning,Combinatorics,考虑一组13个丹麦人、11个日本人和8个波兰人。众所周知,将这组人划分为组的不同方式的数目是13+11+8=32:th Bell数(集合分区的数目)。然而,我们被要求在给定的约束下找到可能的集合分区的数量。问题如下: 如果一个集合分区没有至少由两个人组成的只包含一个国籍的组,则称其为好。此集合有多少个好的分区?(一个小组只能包括一个人。) 蛮力方法需要遍历大约10^26个分区并检查哪些分区是好的。这似乎是不可行的,尤其是如果群体规模较大或有人介绍了其他国籍。有没有聪明的办法 编辑:作为旁注。可能

考虑一组13个丹麦人、11个日本人和8个波兰人。众所周知,将这组人划分为组的不同方式的数目是13+11+8=32:th Bell数(集合分区的数目)。然而,我们被要求在给定的约束下找到可能的集合分区的数量。问题如下:

如果一个集合分区没有至少由两个人组成的只包含一个国籍的组,则称其为。此集合有多少个好的分区?(一个小组只能包括一个人。)

蛮力方法需要遍历大约10^26个分区并检查哪些分区是好的。这似乎是不可行的,尤其是如果群体规模较大或有人介绍了其他国籍。有没有聪明的办法


编辑:作为旁注。可能没有希望找到一个真正好的解决方案。一位备受尊敬的组合数学专家提出了一个相关的问题,我认为,基本上说,相关的问题,因此这个问题,很难精确地解决。

精确的解析解很难,但多项式时间+空间动态规划解很简单

首先,我们需要对组的大小进行绝对排序。我们通过比较我们有多少丹麦人、日本人和波兰人来做到这一点

接下来,要编写的函数就是这个函数

m is the maximum group size we can emit

p is the number of people of each nationality that we have left to split

max_good_partitions_of_maximum_size(m, p) is the number of "good partitions"
we can form from p people, with no group being larger than m
显然,您可以将其编写为一个有点复杂的递归函数,它总是选择要使用的下一个分区,然后用它作为新的最大大小调用自己,并从p中减去分区。如果你有这个函数,那么你的答案就是
max\u good\u partitions\u of\u maximum\u size(p,p)
with
p=[13,11,8]
。但这将是一次暴力搜索,不会在合理的时间内进行


最后,通过缓存对该函数的每个调用来应用,它将在多项式时间内运行。但是,您还必须缓存多项式数量的调用。

这里有一个使用动态编程的解决方案

它从一个空集开始,然后一次添加一个元素并计算所有有效分区

状态空间是巨大的,但请注意,为了能够计算下一步,我们只需要了解分区的以下情况:

  • 对于每个国籍,它包含多少只由该国籍的一名成员组成的集合。(例如:{a})
  • 它包含多少个包含混合元素的集合。(例如:{a,b,c})
对于每种配置,我只存储总计数。例如:

[0, 1, 2, 2] -> 3
{a}{b}{c}{mixed} 
   e.g.: 3 partitions that look like: {b}, {c}, {c}, {a,c}, {b,c}
以下是python中的代码:

import collections
from operator import mul
from fractions import Fraction

def nCk(n,k):
  return int( reduce(mul, (Fraction(n-i, i+1) for i in range(k)), 1) )

def good_partitions(l):
    n = len(l)
    i = 0
    prev = collections.defaultdict(int)
    while l:
        #any more from this kind?
        if l[0] == 0:
            l.pop(0)
            i += 1
            continue
        l[0] -= 1
        curr = collections.defaultdict(int)

        for solution,total in prev.iteritems():
            for idx,item in enumerate(solution):
                my_solution = list(solution)
                if idx == i:
                    # add element as a new set
                    my_solution[i] += 1
                    curr[tuple(my_solution)] += total
                elif my_solution[idx]:
                    if idx != n:
                        # add to a set consisting of one element
                        # or merge into multiple sets that consist of one element
                        cnt = my_solution[idx]
                        c = cnt
                        while c > 0:
                            my_solution = list(solution)
                            my_solution[n] += 1
                            my_solution[idx] -= c
                            curr[tuple(my_solution)] += total * nCk(cnt, c)
                            c -= 1
                    else:
                        # add to a mixed set
                        cnt = my_solution[idx]
                        curr[tuple(my_solution)] += total * cnt

        if not prev:
            # one set with one element
            lone = [0] * (n+1)
            lone[i] = 1
            curr[tuple(lone)] = 1

        prev = curr
    return sum(prev.values())

print good_partitions([1, 1, 1, 1])      # 15
print good_partitions([1, 1, 1, 1, 1])   # 52
print good_partitions([2, 1])            # 4
print good_partitions([13, 11, 8])       # 29811734589499214658370837

它为测试用例生成正确的值。我还用蛮力解(对于小值)对它进行了测试,它产生了相同的结果。

正如你在那里问的那样,得到了你的答案,你可以在这里关闭它。由于表达式中存在一些非线性因素,生成函数很难应用。获得它的洞察力是非常好的,它告诉了一些关于这个问题的事情。然而,不是我想要的确切数字。讨论生成函数的好处。实际上,获得这些数字需要一个聪明的算法(或荒谬的计算能力)。很可能没有什么比暴力更好的了。我把这篇文章贴在这里,是想看看它是否能为比我更擅长算法的人敲响警钟?