[質問]
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]からトレースバックするまで、上記の順方向試行と逆方向トレースを繰り返します。
コード:
#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");
}
結果: