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

参考资料: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 }

 

posted @ 2013-12-30 00:25  rldts  阅读(709)  评论(0编辑  收藏  举报