Algorithm 种群分割算法

Algorithm 种群分割算法,algorithm,combinatorics,Algorithm,Combinatorics,我有一个50个有序整数(1,2,3,…,50)的总体,我寻找一种通用的方法来以“n”的方式对其进行切片(“n”是从1到25的截止点的数量),以保持元素的顺序 例如,对于n=1(一个截止点),有49个可能的分组备选方案([1,2-49],[1-2,3-50],[1-3,4-50],…)。对于n=2(两个截止点),分组备选方案如下:[1,2,3-50],[1,2-3,4-50] 你能推荐一些通用算法来高效地完成这项任务吗 谢谢, 克里斯 谢谢大家的反馈。我审阅了您的所有评论,正在开发一个通用解决方

我有一个50个有序整数(1,2,3,…,50)的总体,我寻找一种通用的方法来以“n”的方式对其进行切片(“n”是从1到25的截止点的数量),以保持元素的顺序

例如,对于n=1(一个截止点),有49个可能的分组备选方案([1,2-49],[1-2,3-50],[1-3,4-50],…)。对于n=2(两个截止点),分组备选方案如下:[1,2,3-50],[1,2-3,4-50]

你能推荐一些通用算法来高效地完成这项任务吗

谢谢, 克里斯


谢谢大家的反馈。我审阅了您的所有评论,正在开发一个通用解决方案,该解决方案将返回所有截止点数量的所有组合(例如,[1,2,3-50],[1,2-3,4-50],…)

再次感谢,
克里斯:你需要截止日期,还是只是在计算。如果你只想数一数,那么很简单:

1截止=(n-1)选项

2个截止值=(n-1)*(n-2)/2个选项

3个截止值=(n-1)(n-2)(n-3)/4个选项

你可以在这里看到图案

如果你真的需要截止线,那么你必须做循环,但是因为n很小,Emilio是对的,就用蛮力来做吧

1切断

for(i=1,i<n;++i)
  cout << i;

对于(i=1,i让序列长度为
N
,切片数为
N

当您注意到,将一个切片选择为n个切片相当于从
n-1
可能的分割点中选择
n-1
(序列中每两个数字之间有一个分割点)时,这个问题就变得更容易了。因此存在这样的切片

要生成所有切片(到n个切片),必须生成从
1到n-1的所有
n-1
数字元素子集


这个问题的精确算法放在这里:

这将生成一个包含所有范围的数组,但我警告您,这将占用大量内存,因为结果太多(50个元素有3个拆分是49*48*47=110544),我甚至没有尝试编译它,所以可能会有错误,但这是我使用的通用算法

typedef std::vector<int>::iterator iterator_t;
typedef std::pair<iterator_t, iterator_t> range_t;
typedef std::vector<range_t> answer_t;
answer_t F(std::vector<int> integers, int slices) {
    answer_t prev;  //things to slice more
    answer_t results; //thin
    //initialize results for 0 slices
    results.push_back(answer(range(integers.begin(), integers.end()), 1));
    //while there's still more slicing to do
    while(slices--) {  
        //move "results" to the "things to slice" pile
        prev.clear(); 
        prev.swap(results); 
        //for each thing to slice
        for(int group=0; group<prev.size(); ++group) { 
            //for each range
            for(int crange=0; crange<prev[group].size(); ++crange) { 
                //for each place in that range
                for(int newsplit=0; newsplit<prev[group][crange].size(); ++newsplit) { 
                    //copy the "result"
                    answer_t cur = prev[group];
                    //slice it
                    range_t L = range(cur[crange].first, cur[crange].first+newsplit);
                    range_t R = range(cur[crange].first+newsplit), cur[crange].second);
                    answer_t::iterator loc = cur.erase(cur.begin()+crange);
                    cur.insert(loc, R);
                    cur.insert(loc, L);
                    //add it to the results
                    results.push_back(cur);
                }
            }
        }
    }
    return results;
}
typedef std::vector::iterator iterator\t;
typedef std::对范围\u t;
typedef std::向量应答;
答案F(标准::向量整数,整数切片){
回答\u t prev;//要切片更多的内容
答案\u t结果;//很薄
//初始化0个切片的结果
结果。推回(回答(范围(integers.begin(),integers.end()),1);
//还有更多的切片要做
而(切片--){
//将“结果”移到“要切片的内容”堆中
prev.clear();
前期掉期(结果);
//每样东西都要切片

对于(int group=0;group,所以您希望以所有可能的方式从49个选项中选择25个分割点。有很多众所周知的方法可以做到这一点

我想提请您注意这个问题的另一面。有49!/(25!*(49-25)!=63 205 303 218 876>=2^45~=10^13不同。因此,如果您要存储它,所需的内存量是32TB*sizeof(组合)。我想它将通过1PB标记

现在,让我们假设您希望动态处理生成的数据。让我们假设您每秒可以处理100万个组合(这里我假设没有并行化)。因此,此任务将花费10^7秒=2777小时=115天


这个问题比乍一看要复杂得多。如果你想在合理的时间内在家解决这个问题,我的建议是改变策略或等待量子计算机的发展。

人口如此之少,你为什么需要效率?蛮力!@Emilio:看起来并没有那么小,但我怀疑不会有这么多如果他想要所有的,还有其他方法。你在找什么?所有可能的切片的列表?随机一个?这里有类似的问题:
for(i=1;<i<n;++i)
  for(j=i+1,j<n;++j)
    for(k=j+1,k<n;++k)
      cout << i << " " << j << " " << k;
typedef std::vector<int>::iterator iterator_t;
typedef std::pair<iterator_t, iterator_t> range_t;
typedef std::vector<range_t> answer_t;
answer_t F(std::vector<int> integers, int slices) {
    answer_t prev;  //things to slice more
    answer_t results; //thin
    //initialize results for 0 slices
    results.push_back(answer(range(integers.begin(), integers.end()), 1));
    //while there's still more slicing to do
    while(slices--) {  
        //move "results" to the "things to slice" pile
        prev.clear(); 
        prev.swap(results); 
        //for each thing to slice
        for(int group=0; group<prev.size(); ++group) { 
            //for each range
            for(int crange=0; crange<prev[group].size(); ++crange) { 
                //for each place in that range
                for(int newsplit=0; newsplit<prev[group][crange].size(); ++newsplit) { 
                    //copy the "result"
                    answer_t cur = prev[group];
                    //slice it
                    range_t L = range(cur[crange].first, cur[crange].first+newsplit);
                    range_t R = range(cur[crange].first+newsplit), cur[crange].second);
                    answer_t::iterator loc = cur.erase(cur.begin()+crange);
                    cur.insert(loc, R);
                    cur.insert(loc, L);
                    //add it to the results
                    results.push_back(cur);
                }
            }
        }
    }
    return results;
}