这个问题很有趣,我期待其他人的解决方案,用一些已知的有前途的算法来解决这个问题......同时我只是给出我的想法。
我不知道您的有序集是什么数据结构,但是
如果我没有错误地理解你的问题,我有一个简单的想法:
也许我们可以使用如下递归公式的简单递归
Split(ordered set A){
if(len(A) == 1) print(A[0])
string group = "";
for(int i in [1, len(A)]){
group = group+" "+A[i];
A remove A[i];
print(group + "," + Split(A));
}
}
基本上它是循环集合,从第一个元素到最后一个元素,在每次迭代中,将第一个 i 元素作为第一个分区,然后删除这些 i 元素,再次调用相同的函数(递归)(取决于您的数据结构,您可能不需要物理删除,而只需传递集合A 的一部分,反正这是概念)
这种方式性能很慢,但考虑到您必须获得所有组合,我认为它可能是可以接受的。
您可以通过一些扭曲来加快速度:事实上,我们只需要知道集合的大小即可获得分区,对于前 4 个元素,或中间 4 个连续元素,或 4 个连续元素在集合中的任何位置,它们都可以用相同的方式进行分区。所以我们确实只需要保存用n元素划分集合的所有方法,这可以增强上述对动态规划的递归:
vector<vector<int>> pos[n];
// pos[i] is my way to store the "configuration" of the partition for i elements
// for example: pos[7] may store [[1,3,7], [2,4,7]]
// Means (1..1),(2..3),(4..7) is one way to partition 7 elements
// (1..2),(3..4),(5..7) is another way
// I want to find pos with this dynamic programming method
Split(int size){
if(pos[size] is not empty){
return pos[size];
}
if(size == 1){
push [1] into pos;
return pos;
}
vector<vector<int>> ret;
for(int i in [1..n]){
vector<vector<int>> subPartitions= Split(n-i);
for(vector<int> partition in [1..size(subPartitions)]){
Add i (offset) to all element in partition
vector<int> newPartition = Merge([i], parition);
push newPartition to ret;
}
}
return pos[size] = ret;
}
这是一个高级概念伪代码,取决于数据结构和实现,它可以以可接受的性能解决您的问题。