r-在C++中的划分与组合(组合数学)实现
r - Partition and Composition (combinatorics) implementation in C++
给定一个大小为M
和N
的矩阵,我们希望用整数值(>=0)填充每一行,使其相加为某个值。
请注意,M
和N
的维度是使用特定公式预先计算的,因此保证在给定所需条件(即下面的sum_val)的情况下匹配填充。
这是在分区库下的R中实现的。
library(partitions)
# In this example, we impose condition
# that each rows must sum up to 2 in total
# And each row has 5 columns
sum_val <- 2
n <- 5
#The above two parameters are predefined.
t(as.matrix(compositions(sum_val, n)))
[,1] [,2] [,3] [,4] [,5]
[1,] 2 0 0 0 0
[2,] 1 1 0 0 0
[3,] 0 2 0 0 0
[4,] 1 0 1 0 0
[5,] 0 1 1 0 0
[6,] 0 0 2 0 0
[7,] 1 0 0 1 0
[8,] 0 1 0 1 0
[9,] 0 0 1 1 0
[10,] 0 0 0 2 0
[11,] 1 0 0 0 1
[12,] 0 1 0 0 1
[13,] 0 0 1 0 1
[14,] 0 0 0 1 1
[15,] 0 0 0 0 2
C++中是否有任何现有的实现?
递归版本
这是一个递归解决方案。你有一个序列a
,在那里你可以跟踪你已经设置的数字。每次递归调用都会为循环中的其中一个元素分配有效的数字,然后为列表的其余部分递归调用该函数。
void recurse(std::vector<int>& a, int pos, int remaining) {
if (remaining == 0) { print(a); return; }
if (pos == a.size()) { return; }
for (int i = remaining; i >= 0; --i) {
a[pos] = i;
recurse(a, pos + 1, remaining - i);
}
}
void print_partitions(int sum_val, int n) {
std::vector<int> a(n);
recurse(a, 0, sum_val);
}
概念验证在http://ideone.com/oJNvmu.
迭代版本
您在下面的评论表明存在性能问题。虽然I/O很可能占用了您的大部分性能,但这里有一个迭代解决方案,可以避免递归方法的函数调用开销。
void print_partitions(int sum_val, int n) {
int pos = 0, last = n - 1;
int a[n]; // dynamic stack-allocated arrays are a gcc extension
for (int i = 1; i != n; ++i)
a[i] = 0;
a[0] = sum_val;
while (true) {
for (int i = 0; i != last; ++i)
printf("%3d ", a[i]);
printf("%3dn", a[last]);
if (pos != last) {
--a[pos];
++pos;
a[pos] = 1;
}
else {
if (a[last] == sum_val)
return;
for (--pos; a[pos] == 0; --pos);
--a[pos];
int tmp = 1 + a[last];
++pos;
a[last] = 0;
a[pos] = tmp;
}
}
}
打印内容的总体思路和顺序与递归方法相同。不是维护计数器remaining
,而是将所有令牌(或您正在分区的任何令牌)立即放在它们所属的位置,以便打印下一个分区。pos
总是最后一个非零字段。如果这不是最后一个,那么您可以通过从pos
中获取一个令牌并将其移动到之后的位置来获得下一个分区。如果是最后一个,则从最后一个位置获取所有令牌,找到在此之前的最后一个非零位置,并从中获取一个令牌,然后将所有这些令牌转储到获取单个令牌的位置之后的位置。
演示运行于http://ideone.com/N3lSbQ.
您可以自己实现:这样的分区由6个整数CCD_ 9定义;对应行中的值只是差x[0]-0
、x[1]-x[0]
、x[2]-x[1]
等。如果列数(5)是固定的,则有4个嵌套循环;如果不是,你可以递归地公式化这个问题。
相关文章:
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 如何在OMNET++中指定与命令行参数组合的输出文件名
- 实现无开销push_back的最佳方法是什么
- 可组合的lambda/std::函数与std::可选
- 使用简单类型列表实现的指数编译时间.为什么
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 如何将这两个函数组合成一个实现?
- 实现虚拟方法的组合行为
- 在C++中实现和包装函数组合以进行惰性计算
- 组合的实现 - 避免初始值设定项列表
- 实现迭代器,以许多向量的组合
- 实现欧几里得除法,根据两个正整数的线性组合编写这两个正整数的最大公约数
- 在C++中实现原始递归组合器
- C++/QML交互式组合框实现
- 组合队列/堆栈的 c++ 实现
- r-在C++中的划分与组合(组合数学)实现
- 在C++中实现置换、组合和PowerSet
- 通过组合实现函子重载