求自然数的组合数的回溯算法

来源:互联网 发布:淘宝上靠谱的鞋店 编辑:程序博客网 时间:2024/05/16 16:56
//自然数的组合数处理头文件
//组合数的回溯算法
/*
 作者:成晓旭
 时间: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     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);


Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=935643


原创粉丝点击