组合的实现:
1.回溯实现
回溯法实现从1~n这n个数中每次取m个数的组合,设置a数组,i从1开始取值,a(1)从1开始到n取值。约定a(1),...,a(i),...,a(m)按升序排列,a(i)后有m-i个大于a(i)的元素,其中最大取值为n,显然a(i)最多取n-m+i,即a(i)回溯的条件是a(i)=n-m+i。
当i<m时,i增加1,a(i)从a(i-1)+1开始取值,直到i=m时输出结果。
当a(i)=n-m+i时,i--回溯,直到i=0时结束。
代码:
- // ICPC.cpp : 定义控制台应用程序的入口点。
- // 排列组合
- #include "stdafx.h"
- #define MAXN 100
- // 组合的回溯实现
- int _tmain(int argc, _TCHAR* argv[])
- {
- int i, j, n, m, a[MAXN];
- long s = 0;
- printf("Input n and m: ");
- scanf("%d%d", &n, &m);
- i = 1; a[1] = 1;
- while (1)
- {
- if (i == m)
- {
- s++;
- for (j = 1; j <= m; j++)
- printf("%d", a[j]);
- printf(" ");
- }
- else
- {
- i++;
- a[i] = a[i - 1] + 1;
- continue;
- }
- // 调整或回溯
- while (a[i] == n - m + i)
- i--;
- if (i > 0)
- a[i]++;
- else
- break;
- }
- printf("/ns=%ld/n", s);
- return 0;
- }
2.组合的递归实现
应用递归设计,设comb(int n, int k)为从1~n这n个数中取k个数的所有组合结果。当组合的第一个数字选定时,其后的数字是从余下的n-1个数中取k-1个数的组合。这就是把从n个数中取k个数的组合问题转化为从n-1个数中取k-1个数的组合问题。设置数组a存放求出的组合数字,约定函数将确定的k个数字组合的第一个数字放在a[k]中,当一个组合救出后,才将数组a中的一个组合输出。
代码:
- // ICPC.cpp : 定义控制台应用程序的入口点。
- // 排列组合
- #include "stdafx.h"
- #define MAXN 100
- int a[MAXN];
- // 组合的递归实现
- void comb(const int n, const int k)
- {
- int i, j;
- for (i = n; i >= k; i--)
- {
- a[k] = i;
- if (k > 1)
- comb(i - 1, k - 1);
- else
- {
- for (j = a[0]; j > 0; j--)
- printf("%d", a[j]);
- printf(" ");
- }
- }
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- int n, m;
- printf("Input n and m: /n");
- scanf("%d%d", &n, &m);
- a[0] = m;
- comb(n, m);
- return 0;
- }
问题提出:在n个不同的元素中取m个允许重复的组合,其组合数为c(n+m-1, m),相当于m个无区别的球放进n个有标志的盒子,每个盒子放的球不加限制的方案数。
|