计数用红色着色m灰色块的方法,其中红色块应以计数至少为n的组进行

Count ways of coloring m grey blocks with red color, in which red blocks should be in groups with count at least n

本文关键字:红色 灰色 方法      更新时间:2023-10-16

我想计算用白色为i黑色块着色的方法,其中红色块应该在计数至少为j的组中。

C(m)m块着色方法的数量(固定n(。

如果m<n,则C(m)=1,因为不能出现红色方块。

否则,颜色要么以灰色块结尾,要么全部为红色,要么以灰色块结尾,后跟n个或多个红色块。

也就是说,如果m>=nC(m)=C(m-1)+1+sum(C(m-i-1) for i=n..m-1).重写这给了C(m)=1+C(m-1)+sum(C(i) for i=0..(m-n-1)).

只要小心一点,我们可以在O(m(时间和空间中计算它。需要注意的是,总和可以增量计算。

这里有一种方法可以做到这一点(python,但应该很容易转换为你想要的任何语言(:

def count(m, n):
C = [0] * (m+1)
s = 0
for i in range(m+1):
if i-n-1 >= 0:
s += C[i-n-1]
C[i] = 1 if i<n else C[i-1] + 1 + s
return C[m]
print(count(7, 3))

稍微小心一点,我们可以注意到我们只在任何时间点访问C的最后n+1元素,因此我们可以将空间使用量减少到 O(n(:

def count(m, n):
C = [0] * (n+1)
s = 0
for i in range(m+1):
if i-n-1 >= 0:
s += C[(i-n-1)%(n+1)]
C[i%(n+1)] = 1 if i<n else C[(i+n)%(n+1)] + 1 + s
return C[m%(n+1)]
print(count(7, 3))

这是一个可能的程序:

#include <iostream>
#include <vector>
int count_rec(int m, int n, std::vector<int>& cache)
{
// Count starts with 1 for no blocks filled
int c = 1;
// i = starting position of current block
for (int i = 0; i <= m - n; i++)
{
// j = number of filled blocks
for (int j = n; j <= m - i; j++)
{
// r = number of blocks available after this block
int r = m - j - i;
// Check if number of combinations for r has already been calculated
if (cache[r] < 0)
{
// If not calculate (subtract 1 block gap)
cache[r] = count_rec(r - 1, n, cache);
}
// Get cached value
c += cache[r];
}
}
return c;
}
int count(int m, int n)
{
if (m <= 0) return 0;
if (n <= 0)
{
n = 1;
}
std::vector<int> cache(m, -1);
return count_rec(m, n, cache);
}
int main()
{
std::cout << "count(7, 3) = " << count(7, 3) << std::endl;
return 0;
}

输出:

count(7, 3) = 17