回溯法解八皇后、幕集输出、迷宫问题

以前虽写过迷宫算法,但是非递归的,今天看数据结构,发现八皇后问题与迷宫问题很相似,八皇后、幕集输出、迷宫问题都可以用回溯法解决,即先序遍历求解过程当中的状态树。

以下是我写用回溯法解八皇后问题:其中 Box类省略了。

package cn.test;

import java.util.ArrayList;
import java.util.List;

/**
 * 八皇后问题
 * @author liubin
 *
 */
public class Test {
//棋盘当前部局 的格子 

public static int max=8;//矩阵行列数
 
public static void main(String[] args) {
  List<Box> lst=new ArrayList<Box>();
 trial(0,max,lst);
 
 

 
/**
 * 递归方法
 * @param row 当前行
 * @param max 矩阵行列数
 */
public static void trial(int row ,int max,List<Box> lst){
 
 if (row>=max){
    //摆放完毕 输出图形 
  
  for(int p=0;p<lst.size();p++){
   int x=lst.get(p).getRow();
   int y=lst.get(p).getColumn();
     switch(y){
     case 0:System.out.println("*0000000");break;
     case 1:System.out.println("0*000000");break;
     case 2:System.out.println("00*00000");break;
     case 3:System.out.println("000*0000");break;
     case 4:System.out.println("0000*000");break;
     case 5:System.out.println("00000*00");break;
     case 6:System.out.println("000000*0");break;
     case 7:System.out.println("0000000*");break;
     }
  }
  
  System.out.println();
  
   //return;
 }else{
    for(int j=0;j<max;j++){
     //检测摆放是否合法
     Box b=new Box();
         b.setRow(row);
         b.setColumn(j);
         lst.add(b);
     if(Legitimate(lst)){//布局合法  
      //System.out.println("合法");
       trial(row+1,max,lst);
     }else{//布局不合法移除
      lst.remove(lst.size()-1);
        }
      //trial(row+1,max);
       }//end else
          lst.remove(lst.size()-1);
     
   
   
 }//end else
}


/**
 * 检测排列是否合法
 * @param lst 要检测的棋子对列
 * @return 是否合法  合法返回true 否则反回false
 */
public static boolean Legitimate(List<Box> lst){

 
 //检测是否同行
 //检测是否有同列

if (lst.size()==1)//队列只有一个元素
  return true;
 
 int x=lst.get(lst.size()-1).getRow();
 int y=lst.get(lst.size()-1).getColumn();
 
   for(int i=lst.size()-2;i>=0;i--){
      int x1=lst.get(i).getRow();
      int y1=lst.get(i).getColumn();
     if(x==x1||y==y1){
      //System.out.println("同行或同列");
      return false;
     }
      if (  Math.abs( ((float)(y1-y))/(x1-x)  )==1  ){//在同一对角线上
      //System.out.println("在同一对角线上");
      return false;
      }
   }
  
 return true;
}
 
}

 

运行结果:

*0000000
0000*000
0000000*
00000*00
00*00000
000000*0
0*000000
000*0000

 

 

以下是幕集输出程序:

package cn.test;

/**
 * 幕集输出程序
 */
import java.util.ArrayList;
import java.util.List;

public class Test {

public static  int var[]={1,2,3};
public static  int k=0;//var 初始序列 
/**
 * 主函数
 * @param args
 */
 public static void main(String[] args) {
  List lst=new ArrayList<Integer>();
  PowerSet(var,lst,k);
 }
 
/**
 * 递归函数
 * @param sa  原始集合
 * @param sb  原始集合的幕集
 * @param k   
 */
 public static void PowerSet(int sa[],List<Integer> sb,int k){
  if(k>sa.length-1){
   //输出幕集
   for(int j=0;j<sb.size();j++){
    System.out.print(sb.get(j)+"  ");
   }
   System.out.println();
  }else{
   //取一个原始集合元素
    sb.add(sa[k++]);
    PowerSet(sa,sb,k);
    //舍一个原始集合元素
    sb.remove(sb.size()-1);
    PowerSet(sa,sb,k);
   
   
  }//end else
 }

}

运行结果:

1  2  3 
1  2 
1  3 

2  3 



 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值