关于将N个相同的球放入M个不同的箱子并打印所有组合的经典问题:如果您希望通过打印所有案例0< M, N
来扩展问题该怎么办?
蛮力方法可以这样做:
for (int i =0; i<M; i++)
{
for (int j =0; j <N; j++)
{
PrintAllCombinations(j,i)
}
}
现在,如果我们研究第一对m和n的输出,我们看到每个先前迭代的输出是下一个迭代的子集。在我看来,我们可以应用动态算法来利用这种现象。但是,因为我们仍然需要对每个n
进行分区,例如n=3 = 3 +0, 2+1, 1+2
。我们仍然需要做很多冗余的组合计算。
任何想法都会改进吗?
答案 0 :(得分:1)
让S[i][j]
为i
个分区中j
个球的组合数。
S[0][j] = 1
适用于所有j,因为唯一的组合是将所有分档都清空。
S[i][1] = 1
对于所有我来说,因为唯一的组合是将所有球放在一个箱子里。
对于其他每一个,j S[i][j] = sum(x = 0 -> i, S[i-x][j-1])
。也就是说,对于每个其他位置,您可以通过将每个可能数量的球分配到最后一个bin并计算得到的组合数来计算组合数。
如果要打印出组合,可以使用实际组合替换计数,并在取总和中的内部组合时附加值x
。这将占用大量内存而速度没有太大提升。只需进行递归并重复计算,因为您仍然受到解决方案数量的限制。