回溯算法

引言:

寻找问题的解的一种可靠的方法是首先列出所有候选解,然后依次检查每一个,在检查完所有或部分候选解后,即可找到所需要的解。理论上,当候选解数量有限并且通过检查所有或部分候选解能够得到所需解时,上述方法是可行的。不过,在实际应用中,很少使用这种方法,因为候选解的数量通常都非常大(比如指数级,甚至是大数阶乘),即便采用最快的计算机也只能解决规模很小的问题。对候选解进行系统检查的方法有多种,其中回溯和分枝定界法是比较常用的两种方法。按照这两种方法对候选解进行系统检查通常会使问题的求解时间大大减少(无论对于最坏情形还是对于一般情形)。事实上,这些方法可以使我们避免对很大的候选解集合进行检查,同时能够保证算法运行结束时可以找到所需要的解。因此,这些方法通常能够用来求解规模很大的问题。

算法思想:

回溯(backtracking)是一种系统地搜索问题解答的方法。为了实现回溯,首先需要为问题定义一个解空间(solution space),这个空间必须至少包含问题的一个解(可能是最优的)。
     下一步是组织解空间以便它能被容易地搜索。典型的组织方法是图(迷宫问题)或树(N皇后问题)。
      一旦定义了解空间的组织方法,这个空间即可按深度优先的方法从开始节点进行搜索。

回溯方法的步骤如下:
     1) 定义一个解空间,它包含问题的解。
     2) 用适于搜索的方式组织该空间。
     3) 用深度优先法搜索该空间,利用限界函数避免移动到不可能产生解的子空间。

回溯算法的一个有趣的特性是在搜索执行的同时产生解空间。在搜索期间的任何时刻,仅保留从开始节点到当前节点的路径。因此,回溯算法的空间需求为O(从开始节点起最长路径的长度)。这个特性非常重要,因为解空间的大小通常是最长路径长度的指数或阶乘。所以如果要存储全部解空间的话,再多的空间也不够用。

八皇后问题:

public class Empress {
	static int n = 8;
	static int num = 0;
	static int[] a = new int[9];
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Empress s = new Empress();
		s.findQueen(1);
		System.out.println(num);
	}
	
	public void findQueen(int t) {//t表示第几行
		if(t > n) {
			num++;//如果大于8,则找到一个解,输出
			print(a);
		} else {
			for(int i = 1; i <= n;i++) {//下一个节点有n个选择
				a[t] = i;//a[t]表示第几列
				if(isValid(t)) {//符合皇后规则,继续寻找下一个节点。不符合,则寻找下一列.
					findQueen(t+1);
				}
			}
		}
	}
	public void print(int[] a) {//打印
		for(int i = 1; i < a.length;i++ ) {
			System.out.print("皇后 " + i + "位于" + "第" + i + "行" + a[i] + "列 ");
		}
		System.out.println("-----------------");
	}
	public boolean isValid(int t){//判断是否合法,即两个皇后既不能在同一行同一列同一斜线。
		for(int i = 1;i < t;i++) {
			if(Math.abs(t-i) == Math.abs(a[t]-a[i]) || a[i] == a[t]){
				return false;
			}
		}
		return true;
	}
}

种一棵树最好的时间是十年前,其次是现在!



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值