回溯算法_组合问题

这类问题通常需要输出可能的所有组合。我对回溯算法解题过程的理解是:将所有可能的组合形成一个树/森林,遍历其所有叶节点,输出根节点到这个叶节点这条路径所代表的组合。

例如:找出从自然数1~n中任取r个数的所有组合。

不妨设n=5,r=3,用a[3]输出可能的组合。则所有可能的组合为:

1 2 3,1 2 4,1 2 5,1 3 4,1 3 5,1 4 5;

2 3 4,2 3 5,2 4 5;

3 4 5;

用树来表示: 

                                1                                    |                        2                      |          3         i=0

                                                                      |                                                |                        

      2                        3                        4          |               3                 4            |          4         i=1

                                                                      |                                                |

3    4    5                4    5                    5          |            4     5             5            |          5         i=2

 第i=0层:数字填入a[0],一开始为1,逐渐递加到3                 3+(imax-i)=n,imax=r-1。

 第i=1层:数字填入a[1],一开始为a[0]+1,逐渐增加到4 

 第i=2曾:数字填入a[2],一开始为a[1]+1,逐渐增加到5       

int n=5,r=3;  //假设
int i=0;      //从第0层开始
int a[r];     //用a[r]储存、输出这个组合
a[0]=1;       //这个组合的第一个数从1开始

do{//一直循环直到到达最后一个叶节点为止
	if(a[i]<=n-r+1+i){  //还可以向后
		if(i==r-1){    //此时到达最后一层
			//输出a[0]~a[2],即输出这个组合
			a[i]++;    //访问下一个叶节点
		}
		else{          //没有到达最后一层的话,向下访问
			i++;
			a[i]=a[i-1]+1;
		}
	}
	else{    //不可以再向后了
		if(i==0){        //深度优先后移,此时最后一个节点也无法后移时,结束
			return;
		}
		i--;    //上一个节点后移
		a[i]++;
	}
}
while(1);

扩展到所有变量n,r的代码: 

#include <stdio.h>
#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()
{
	int x, y;
	printf("请规定截止数和几个数组合(用,分割的整数):");
	scanf("%d,%d",&x,&y);
	printf("自然数1~%d中%d个数的任意组合有:\n", x, y);
	comb(x, y);
}

引用自:C语言经典回溯算法之解决数的组合问题(详解)_c语音组合问题是用回溯算法。-CSDN博客 

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值