首先介绍一下回溯算法:
定义来自《百度百科》......名字着很高大上,实际上就是试探法,逐步试错找到最终的可行解。
重要的一点是解空间通常是在搜索可行解过程中动态产生的,所以程序中通常利用到递归的算法,如后面介绍的八皇后问题。这点区别与于前段时间所写的模拟退火算法,模拟退火是首先确定解空间,然后以一定的概率接受当前发现的次优解,从而有更大的可能避免局部最优而得到全局最优。
简单介绍一下八皇后问题:
在8×8格的国际象棋上摆放八个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。
下面是用回溯法写的java程序,效率很低,可以用多种方法进行优化,以后补充(希望我会进行优化更新博客.........)
public class EightQueen { private int[] resultRange; private int rangeNum=0; public EightQueen(int num) { this.resultRange=new int[num]; } public static void main(String[] args) { long startMillis=System.currentTimeMillis(); EightQueen eQueen=new EightQueen(8); eQueen.rangeQueen(0); long endMillis=System.currentTimeMillis(); System.out.println("共"+eQueen.rangeNum+"种方案"); System.out.println("共消耗时间:"+(endMillis-startMillis)); } //回溯法-----放置皇后 private void rangeQueen(int num) { if(num>=resultRange.length) { printResult(); rangeNum++; return; } for(int i=0;i<resultRange.length;i++) { resultRange[num]=i; if(checkQueen(num)) { rangeQueen(num+1);//迭代求解 } } } //检查是否存在同列或同斜线的皇后 private boolean checkQueen(int n) { // TODO Auto-generated method stub for(int i=0;i<n;i++) { if(resultRange[n]==resultRange[i] || Math.abs(n-i)==Math.abs(resultRange[n]-resultRange[i])) { return false; } } return true; } //打印出每一种方案以及最终的方案数 private void printResult() { System.out.println("第"+(rangeNum+1)+"种方案"); for(int i=0;i<resultRange.length;i++) { for(int j=0;j<resultRange.length;j++) { if(j==resultRange[i]) { System.out.print("* "); } else { System.out.print(0+" "); } } System.out.println(); } System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"); } }
运行结果截图: