给定大小为M
和N
的矩阵,我们希望用整数值(> = 0)填充每一行,以便它总和到某个值。
请注意,M
和N
的维度是使用某个公式预先计算的,因此可以保证匹配给定所需条件的填充(即下面的sum_val)。
这是在Partition library下的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 ++中是否存在任何实现?
答案 0 :(得分:2)
这是一个递归解决方案。您有序列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("%3d\n", 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运行。
答案 1 :(得分:1)
您可以自己实施:
这样的分区由6个整数0 <= x[0] <= x[1] <= x[2] <= x[3] <= 2
定义;
相应行中的值只是差异x[0]-0
,x[1]-x[0]
,x[2]-x[1]
等。
如果列数(5)是固定的,则有4个嵌套循环;
它不是,你可以递归地表达问题。