求解组合问题的一个迭代算法

参考资料:http://blog.csdn.net/sharpdew/article/details/755074

实际上这个算法的思路就是如下,举例说明比较直观一些,比如说计算{1,2,3,4,5}的3位组合

搜索过程如下

  以order数组的内容为例,order[1]就指向a[0],order[2]指向a[1]以此类推

  order是一个数组,用来存放组合数在a[]中下标,order[0]作为一个flag来控制迭代循环何时结束,order[i]表示a[i-1],通过修改order的内容来寻找组合,实际上跟直接找a[i]的组合是一样的

  下划线表示回溯,黑体表示新的值,不符合要求的搜索结果用<strike></strike>划掉,因为a的下标最大就是4,所以当order的某个值为4的时候,就可以回溯了:

012,013,014,01_,02_,022,023,024,02_,03_,033,034,03_,04_,044,04_,0__,1__,11_,12_,122,123,124,12_,13_,133,134,13_,14_,144,14_,1__,2__,22_,23_,233,234,23_,24_,244,24_,2__,3__,33_,34_,3__,4__,___

 1 #include "stdafx.h"

 2 

 3 int combine(int a[], int n, int m)

 4 {

 5     m = m > n ? n : m; // let's say m == 10, n == 9, so C(9, 10) is not correct, we compute C(9, 9)

 6 

 7     int* order = new int[m + 1];

 8     for (int i = 0; i <= m; i++)

 9         order[i] = i - 1; // 注意这里order[0]=-1用来作为循环判断标识

10 

11     int count = 0;

12     int k = m;

13     bool flag = true; // 标志找到一个有效组合

14     while (order[0] == -1)

15     {

16         if (flag) // 输出符合要求的组合

17         {

18             for (int i = 1; i <= m; i++)

19                 std::cout << a[order[i]] << " ";

20             std::cout << std::endl;

21             count++;

22             flag = false;

23         }

24         order[k]++; // 在当前位置选择新的数字

25         if (order[k] == n) // 当前位置已无数字可选,回溯

26         {

27             order[k--] = 0;

28             continue;

29         }

30         if (k < m) // 更新当前位置的下一位置的数字          

31         {

32             order[++k] = order[k - 1];

33             continue;

34         }

35         if (k == m)

36             flag = true;

37     }

38     delete[] order;

39     order = NULL;

40     return count;

41 }

42 

43 int main() {

44     int a[] {1, 2, 3, 4, 5};

45     combine(a, 5, 3);

46     system("pause");

47     return 0;

48 }

 

你可能感兴趣的:(算法)