//自然数的组合数处理头文件
//组合数的回溯算法
/*
作者:成晓旭
时间:2001年10月9日(10:00:38-10:20:00)
内容:完成组合数的回溯算法
时间:2001年10月7日(21:09:38-22:09:00)
内容:完成二叉树的前,中序遍历(非递归)
时间:2001年10月8日(10:09:38-11:29:00)
内容:完成查找二叉树的静,动态查找(非递归)
*/
#include "stdlib.h"
#define MAXN 100
int number[MAXN];
/*
自然数的组合数回溯算法Comb_Back()
参数定义:
int m:被求组合数的自然数
int n:要求组合数的自然数个数
编程思想:(此分析以调用Comb_Back(5,3)为例)
采用回溯法处理组合数,将找到的组合以从小到大顺序存入number[0],
number[1],...,number[n-1]中,组合的元素满足如下关系式:
(1)number[i+1] > number[i];
(2)number[i]-i <= m -n+1;
首先,放弃组合数个数为n的条件,候选组合数从只有一个数字1开始(设n=1)
因为,该候选组合满足除问题规模之外的全部条件;
接着,扩大其规模,并使其满足条件(1),候选组合改为1,2,继续此过程,得到
候选组合1,2,3,该候选组合满足包括问题规模在内的全部条件,因而得到一个可
行的解;
在得到的解的基础上,选下一个候选解,试着调整组合中的最后一个元素的值
为(4,5),得到1,2,4,及1,2,5两个可行的解<这就是试探>;
当再试图调整最后一个元素发生越界时,就不能再做调整,此时,需要从最后
一个元素回溯至其前一个元素<这就是回溯>,然后向前试探得到可行解(1,3,4)及
(1,3,5);
重复上述向前试探和向后回溯,直到当需要从第一个number[0]再回溯时,表
明已经找到问题的全部可行解,程序结束.
*/
void Comb_Back(int m,int n)
{
int i,j;
i = 0;
number[i] = 1;
do
{
if(number[i]-i <= m-n+1)/*还能向前试探*/
{
if(i==n-1)/*已经找到一个可行的组合解*/
{
for(j=0;j<n;j++)
printf("%4d",number[j]);
printf("/n");
number[i]++;/*调整*/
continue;
}
i++;/*扩展,向前试探*/
number[i] = number[i-1]+1;
}
else/*不能试探,理应回溯*/
{
if(i==0)return;/*找到所有可行的解,结束*/
number[--i]++;/*调整,向后回溯*/
}
}while(1);
}
//组合数的回溯算法
/*
作者:成晓旭
时间:2001年10月9日(10:00:38-10:20:00)
内容:完成组合数的回溯算法
时间:2001年10月7日(21:09:38-22:09:00)
内容:完成二叉树的前,中序遍历(非递归)
时间:2001年10月8日(10:09:38-11:29:00)
内容:完成查找二叉树的静,动态查找(非递归)
*/
#include "stdlib.h"
#define MAXN 100
int number[MAXN];
/*
自然数的组合数回溯算法Comb_Back()
参数定义:
int m:被求组合数的自然数
int n:要求组合数的自然数个数
编程思想:(此分析以调用Comb_Back(5,3)为例)
采用回溯法处理组合数,将找到的组合以从小到大顺序存入number[0],
number[1],...,number[n-1]中,组合的元素满足如下关系式:
(1)number[i+1] > number[i];
(2)number[i]-i <= m -n+1;
首先,放弃组合数个数为n的条件,候选组合数从只有一个数字1开始(设n=1)
因为,该候选组合满足除问题规模之外的全部条件;
接着,扩大其规模,并使其满足条件(1),候选组合改为1,2,继续此过程,得到
候选组合1,2,3,该候选组合满足包括问题规模在内的全部条件,因而得到一个可
行的解;
在得到的解的基础上,选下一个候选解,试着调整组合中的最后一个元素的值
为(4,5),得到1,2,4,及1,2,5两个可行的解<这就是试探>;
当再试图调整最后一个元素发生越界时,就不能再做调整,此时,需要从最后
一个元素回溯至其前一个元素<这就是回溯>,然后向前试探得到可行解(1,3,4)及
(1,3,5);
重复上述向前试探和向后回溯,直到当需要从第一个number[0]再回溯时,表
明已经找到问题的全部可行解,程序结束.
*/
void Comb_Back(int m,int n)
{
int i,j;
i = 0;
number[i] = 1;
do
{
if(number[i]-i <= m-n+1)/*还能向前试探*/
{
if(i==n-1)/*已经找到一个可行的组合解*/
{
for(j=0;j<n;j++)
printf("%4d",number[j]);
printf("/n");
number[i]++;/*调整*/
continue;
}
i++;/*扩展,向前试探*/
number[i] = number[i-1]+1;
}
else/*不能试探,理应回溯*/
{
if(i==0)return;/*找到所有可行的解,结束*/
number[--i]++;/*调整,向后回溯*/
}
}while(1);
}