Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1072993
  • 博文数量: 77
  • 博客积分: 11498
  • 博客等级: 上将
  • 技术积分: 1840
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-04 11:10
文章分类

全部博文(77)

文章存档

2011年(1)

2010年(16)

2009年(5)

2008年(55)

分类: C/C++

2008-12-04 19:08:55

以前写了篇文章(见这里)介绍了一般组合问题的两个常见解法,这里再对可重复组合问题进行分析。

可重复组合问题是指,在计算(生成)组合时可以允许元素重复的一类组合问题。例如,对于有四个元素的集合{a, b, c, d},其可重复组合C(4, 3)有20个:aaa, aab, aac, aad, abb, abc, abd, acc, acd, add, bbb, bbc, bbd, bcc, bcd, bdd, ccc, ccd, cdd, ddd。

用P(n, k)表示从n个元素中选出k个元素(允许重复)的组合问题,那么此问题可以分解为两个子问题:P(n, k-1)和P(n-1, k),
解释如下:
P(n, k)中n个元素的所有k元素组合可以分成两部分。
第一部分的每个组合均以第一个元素开始,再连接上k-1个元素的组合,即再连接上P(n,k-1)的每一个组合;
第二部分的每个组合不含有第一个元素,即P(n-1, k)中的每一个组合(此时元素为后n-1个元素)。
因此,P(n, k)分解为P(n, k-1)和P(n-1, k)。

如果用f(n, k)表示P(n, k)中的组合数,那么有:
(1)当k = 1时,f(n, k) = n
(2)当n = 1时,f(n, k) = 1
(3)当k > 1且n > 1时,f(n, k) = f(n, k -1) + f(n-1, k)

此外,有公式f(n, k) = C(n + k -1, k)(表示n+k-1选k的组合数,没有重复元素),这可以用归纳法证明,这里就不啰嗦了。

C++实现如下:

F:\tmp>type ttt.cpp
#include
#include
#include
#include
#include
using namespace std;

template
void CalcRepeatableCombination(const ElemType elements[], int num, int k,
    vector &pre)
{
    if (k == 1) {
        for (int i = 0; i < num; ++i) {
            copy(pre.begin(), pre.end(), ostream_iterator(cout));
            cout << elements[i];
            cout << endl;
        }
        return;
    }

    if (num == 1) {
        ostream_iterator outIter(cout);
        outIter = copy(pre.begin(), pre.end(), outIter);
        fill_n(outIter, k, elements[0]);
        cout << endl;
        return;
    }

    pre.push_back(elements[0]);
    CalcRepeatableCombination(elements, num, k - 1, pre);
    pre.pop_back();

    CalcRepeatableCombination(elements + 1, num - 1, k, pre);
}

template
void CalcRepeatableCombination(const ElemType elements[], int num, int k)
{
    assert(num >= k && k >= 1);
    vector one;
    CalcRepeatableCombination(elements, num, k, one);
}

int main()
{
    char elements[] = {'a', 'b', 'c', 'd'};
    CalcRepeatableCombination(elements, 4, 3);
}

F:\tmp>g++ ttt.cpp

F:\tmp>a.exe
aaa
aab
aac
aad
abb
abc
abd
acc
acd
add
bbb
bbc
bbd
bcc
bcd
bdd
ccc
ccd
cdd
ddd

F:\tmp>
阅读(3080) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~