回溯算法1——组合问题

【问题】
找出从自然数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");
}

结果:

猜你喜欢

转载自blog.csdn.net/baidu_36669549/article/details/104156704