Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.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
C++ 大集合的第n个或任意组合_C++_Algorithm_Permutation_Combinations - Fatal编程技术网

C++ 大集合的第n个或任意组合

C++ 大集合的第n个或任意组合,c++,algorithm,permutation,combinations,C++,Algorithm,Permutation,Combinations,假设我有一组来自[0,…,499]的数字。当前使用C++代码> STD::NExtx置换< /COD>顺序生成组合。作为参考,我提取的每个元组的大小是3,因此我返回顺序结果,如[0,1,2],[0,1,3],[0,1,4]。。。[497498499] 现在,我想对代码进行并行化,这样连续生成这些组合就不再有效了。是否有任何现有算法可用于计算500个数字中3的第i个组合 我想确保每个线程,不管它得到的循环的迭代次数如何,都可以基于它正在迭代的I计算一个独立的组合。因此,如果我想要线程1中I=38的

假设我有一组来自
[0,…,499]
的数字。当前使用C++代码> STD::NExtx置换< /COD>顺序生成组合。作为参考,我提取的每个元组的大小是3,因此我返回顺序结果,如
[0,1,2],[0,1,3],[0,1,4]。。。[497498499]

现在,我想对代码进行并行化,这样连续生成这些组合就不再有效了。是否有任何现有算法可用于计算500个数字中3的第i个组合

我想确保每个线程,不管它得到的循环的迭代次数如何,都可以基于它正在迭代的
I
计算一个独立的组合。因此,如果我想要线程1中
I=38
的组合,我可以计算
[1,2,5]
,同时将线程2中的
I=0
计算为
[0,1,2]

编辑下面的陈述无关紧要,我把自己搞糊涂了


我看过一些算法,它们利用阶乘从左到右缩小每个元素的范围,但我不能把它们当作500!当然不适合记忆。有什么建议吗?

您可以将500个对象中的3个对象描述为三个
(i,j,k)
,其中
i
是从0到499的数字(第一个数字的索引),
j
范围从0到498(第二个的索引,跳过第一个数字),而
k
范围从0到497(最后一个的索引,跳过之前选择的两个数字)。因此,枚举所有可能的选择实际上非常容易:从
(0,0,0)开始
,递增
k
直到达到其最大值,然后递增
j
并将
k
重置为0,依此类推,直到
j
达到其最大值,依此类推,直到
j
达到其自身的最大值;然后递增
i
并将
j
k
重置并继续

如果这个描述听起来很熟悉,那是因为它的工作原理与增加一个以10为基数的数字的工作原理完全相同,只是基数要有趣得多,而且实际上基数在数字之间是不同的。你可以利用这一观点来实现这个想法的一个非常简洁的版本:对于从0到500*499*498的任何整数
n
,你可以得到:

struct {
  int i, j, k;
} triple;

triple AsTriple(int n) {
  triple result;
  result.k = n % 498;
  n = n / 498;
  result.j = n % 499;
  n = n / 499;
  result.i = n % 500;  // unnecessary, any legal n will already be between 0 and 499
  return result;
}

void PrintSelections(triple t) {
  int i, j, k;
  i = t.i;
  j = t.j + (i <= j ? 1 : 0);
  k = t.k + (i <= k ? 1 : 0) + (j <= k ? 1 : 0);
  std::cout << "[" << i << "," << j << "," << k << "]" << std::endl;
}

void PrintRange(int start, int end) {
  for (int i = start; i < end; ++i) {
    PrintSelections(AsTriple(i));
  }
}
struct{
int i,j,k;
}三重;
三重阿斯特里普(int n){
三重结果;
结果:k=n%498;
n=n/498;
结果:j=n%499;
n=n/499;
result.i=n%500;//不需要,任何合法的n都将在0和499之间
返回结果;
}
无效打印选择(三重t){
int i,j,k;
i=t.i;

j=t.j+(i如果您正在寻找一种方法来获得唯一组合的字典索引或秩,而不是排列,那么您的问题属于二项式系数。二项式系数处理的问题是,在总共N个项目的K组中选择唯一组合

我用C#编写了一个类来处理处理处理二项式系数的常用函数。它执行以下任务:

  • 将任意N选择K的所有K索引以良好的格式输出到文件中。K索引可以替换为更多描述性字符串或字母

  • 将K-索引转换为已排序的二项式系数表中条目的适当词典索引或秩。此技术比依赖迭代的较旧已发布技术快得多。它通过使用Pascal三角形固有的数学特性来实现这一点,与在集合上迭代相比非常有效

  • 将排序后的二项式系数表中的索引转换为相应的K索引。我相信它也比旧的迭代解决方案快

  • 使用此方法计算二项式系数,它不太可能溢出,并且适用于较大的数字

  • 该类是用.NET C#编写的,提供了一种管理与问题相关的对象(如果有)的方法通过使用泛型列表。该类的构造函数接受一个名为InitTable的bool值,如果为true,将创建一个泛型列表来保存要管理的对象。如果该值为false,则它将不会创建该表。使用上述4种方法不需要创建该表。提供了访问器方法来访问e桌

  • 有一个相关的测试类,它展示了如何使用这个类及其方法。它已经用2个案例进行了广泛的测试,并且没有已知的bug

  • 要阅读有关此类的信息并下载代码,请参阅

    以下测试代码将遍历每个唯一的组合:

    public void Test10Choose5()
    {
       String S;
       int Loop;
       int N = 500;  // Total number of elements in the set.
       int K = 3;  // Total number of elements in each group.
       // Create the bin coeff object required to get all
       // the combos for this N choose K combination.
       BinCoeff<int> BC = new BinCoeff<int>(N, K, false);
       int NumCombos = BinCoeff<int>.GetBinCoeff(N, K);
       // The Kindexes array specifies the indexes for a lexigraphic element.
       int[] KIndexes = new int[K];
       StringBuilder SB = new StringBuilder();
       // Loop thru all the combinations for this N choose K case.
       for (int Combo = 0; Combo < NumCombos; Combo++)
       {
          // Get the k-indexes for this combination.  
          BC.GetKIndexes(Combo, KIndexes);
          // Verify that the Kindexes returned can be used to retrive the
          // rank or lexigraphic order of the KIndexes in the table.
          int Val = BC.GetIndex(true, KIndexes);
          if (Val != Combo)
          {
             S = "Val of " + Val.ToString() + " != Combo Value of " + Combo.ToString();
             Console.WriteLine(S);
          }
          SB.Remove(0, SB.Length);
          for (Loop = 0; Loop < K; Loop++)
          {
             SB.Append(KIndexes[Loop].ToString());
             if (Loop < K - 1)
                SB.Append(" ");
          }
          S = "KIndexes = " + SB.ToString();
          Console.WriteLine(S);
       }
    }
    
    public void Test10Choose5()
    {
    字符串S;
    内环;
    int N=500;//集合中的元素总数。
    int K=3;//每组中的元素总数。
    //创建获取所有数据所需的bin coeff对象
    //此N选择K组合的组合。
    BinCoeff BC=新的BinCoeff(N,K,false);
    int NumCombos=BinCoeff.GetBinCoeff(N,K);
    //Kindexes数组指定lexigraphic元素的索引。
    int[]KIndexes=新的int[K];
    StringBuilder SB=新的StringBuilder();
    //循环通过此N选择K案例的所有组合。
    for(int-Combo=0;Comboint k = 527; //The kth combination is calculated
    int N=500; //Number of Elements you have
    int a=0,b=1,c=2; //a,b,c are the numbers you get out
    
    while(k >= (N-a-1)*(N-a-2)/2){
        k -= (N-a-1)*(N-a-2)/2;
        a++;
    }
    b= a+1;
    while(k >= N-1-b){
        k -= N-1-b;
        b++;
    }
    
    c = b+1+k;
    
    
    cout << "["<<a<<","<<b<<","<<c<<"]"<<endl; //The result