回溯算法思想

回溯算法思想

回溯法又叫试探法,它是一种系统的搜索问题解的方法。该算法设计思想适用相当广泛。例如,棋手思考下一步应该走哪里的时候,就会采取试探的方法,当然是在脑中试探。首先想一下下一步的位置,计算对手的应对,再计算自己的应对,若对手的应对对我不利,则取消资格设想。然后再计算另一种想法。

算法思路:

​ 回溯法是计算机中常用到的算法,很多问题都可以用到它。回溯法是搜索算法的一种控制策略。它的基本思想是:从问题的某一种状态(一般是默认的初始状态)出发,搜索从这种状态出发所能达到的有状态,当一条路走到尽头时,就退后几步,接着从另外一种状态出发,继续搜索,直到所有的“路”都尝试了。

编程经验:
对于常见的迷宫问题,就可以使用回溯法进行解决。具体过程为:进入迷宫后,
先随意选择一个方向前进,一步一步的向前试探,如果碰到死胡同,说明已经
没有路了,这时,首先看其他方向是否还有路可走,如果有,则沿着该方向继
续向前试探走,如过无路可走,就返回一步,再看看其他方向是否有路可走;
如果有路,则沿着该方向再向前试探走。按照这个规则不断试探,回溯,再搜
索,直到找到新的出路或者从原路返回入口处无解为止。

一般的递归回溯算法的C语言伪代码如下:

对解集合中的各解进行试探
{
if(满足条件)
{
    保存结果
    if(完成集合中所有解的试探)
    	输出解
    else
    	重复本过程进行下一步的试探(递归调用本函数)
}else
	恢复至上一步保存结果之前的状态,进行另一步的试探(递归调用本函数)
}
实例:

彩票号码是由一些数字组合成的,生成彩票号码,其实就是将不同的数字进行不同的组合。例如:假设由一种彩票,每注由7个1~29的数字组成,且这7个数字不能相同,编写程序生成所有的号码组合。

按照常规思想,我们会用循环嵌套来解决,即用七个for循环来解决问题。
可是却十分的麻烦,代码太长,效率也不高。而且也没有通用性。

其实解决这类问题最好的办法就是试探法,逐步计算出所有的组合。

首先,可以按照如下顺序生成彩票号:

29 28 27 26 25 24 23

29 28 27 26 25 24 22

29 28 27 26 25 24 21

29 28 27 26 25 24 1

29 28 27 26 25 23 22

​ 从上面列出的号码顺序可以看出,生成彩票号码组合时,首先变化最后一位,当最后一位是1时,将回溯计算倒数第二位,使该位减少1,然后再变化最后一位数,通过这样的递归调用,即可生成所用的号码组合。

​ 如果要生成N位数的彩票号码,则从N位开始变化即可。

代码实现:
#include <cstdio>
#include <conio.h>
#include <iostream>
using namespace std;
#define MAXN 7
#define NUM 29
int num[NUM];
int lottery[MAXN];
void combine(int n,int m)
{
	int i,j;
	for(i=n;i>=m;i--)
	{
		lottery[m-1]=num[i-1];
		if(m>1)
		combine(i-1,m-1);
		else {
			for(j=MAXN-1;j>=0;j--)
			{
				printf("%3d",lottery[j]);
			}
			getch();
			cout<<endl;
		}
	}
}
int main()
{
	int i,j;
	for(i=0;i<NUM;i++)
	{
		num[i]=i+1;
	}
	for(i=0;i<MAXN;i++)
	{
		lottery[i]=0;
	}
	combine(NUM,MAXN);
	getch();
	return 0;
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值