【问题】
找出从自然数1~n中任取r个数的所有组合。例如n=5,r=3的所有组合如下:
(1)1,2,3
(2)1,2,4
(3)1,2,5
(4)1,3,4
(5)1,3,5
(6)1,4,5
(7)2,3,4
(8)2,3,5
(9)2,4,5
(10)3,4,5
按照回溯法的思想,将找到的组合以从小到大的顺序存放到数组a[0],a[1], . a[r-1]中,组合中的元素满足以下性质:
(1) a[i+1]>a[i], 即后一个数大于前个数;
(2) a[i]-i<=n-r+1。
按照回溯法思想,找解过程描述如下:
首先暂时不考虑组合数个数为r的条件,候选组合从只有一个数字1开始。因为该候选解满足除问题规模之外的全部条件,扩大其规模,并使其满足上述条件(1),得到候选组合1, 2。继续这一过程,得到候选解1、2、3。该候选解满足包括问题规模在内的全部条件,因而是一个解。 在该解的基础上,选下一个候选解,因a[2]上的 3调整为4和5都满足问题的全部要求,得到解1,2,4和1,2, 5。由于对5不能继续进行调整,就要从a[2]回溯到a[1],可以将a[1]从2调整为3,并向前试探,得到解1,3, 4。重复上述向前试探和向后回溯,直到从a[0]再回溯时,表明已经找完问题的全部解。
code:
#include<stdio.h>
#include <iostream>
#define MAX 100
int a[MAX];
void comb(int n, int r)
{
int i, j;
i = 0;
a[i] = 1;
do
{
if (a[i] - i <= n - r + 1) /*还可以向前试探*/
{
if (i == r - 1) /*找到一个组合*/
{
for (j = 0; j < r; j++) /*输出一个组合*/
printf("%4d", a[j]);
printf("\n");
a[i]++;
continue;
}
i++; /*向前试探*/
a[i] = a[i - 1] + 1;
}
else /*回溯*/
{
if (i == 0) /*找完全部解*/
return;
a[--i]++;
}
} while (1);
}
void main()
{
printf("正整数1~5中的3个数的任意组合:\n");
comb(5, 3);
system("pause");
}
结果: