java 实现大狮子为A,小狮子为a,大老虎为B,小老虎为b,大狼为C,小狼为c 动物一起过河问题

/**
 *
 * @author z84002131
 *  很久很久以前,在一个森林里,有狮子,老虎和狼,他们应大象的邀请,要到大象家做客。去的路上被一条小河拦住了,需要过河,只有一个独木舟。现在已知:
 *  1.总共有6只,分别是狮子爸爸,小狮子,老虎爸爸,小老虎,狼爸爸和小狼。
 *  2.小家伙们都比较弱小,如果没有爸爸罩着就会被旁边的大家伙吃掉。
 *  3.独木舟最多能坐2人,无视每只的大小。
 *  4.大家伙都会划船,小家伙里只有小老虎会划船。
 *  求:安全过河方法。
 *  提示:可以设大狮子为A,小狮子为a,大老虎为B,小老虎为b,大狼为C,小狼为c。再形象的用竖线来表示河,0表示船,那么题目就是要求画出
 *  AaBbCc|0  |
 *  ...
 *        |  0|AaBbCc
 *  中间被...省略的步骤
 */

 

import java.util.Vector;

public class AcrossTheRiver {

 private static final int SHIP = 0;
 private static final int LION_A = 1;
 private static final int LION_a = 2;
 private static final int TIGER_B = 3;
 private static final int TIGER_b = 4;
 private static final int WOLF_C = 5;
 private static final int WOLF_c = 6;
 private static final int TOTAL_STATUS = 7;
 
 //用一个整型int来存放当前的状态,第1位为0表示SHIP在左岸,第1位为1表示SHIP在右岸
 //                             第2位为0表示LION_A在左岸,第2位为1表示LION_A在右岸
 //                             第3位为0表示LION_a在左岸,第3位为1表示LION_a在右岸,往下以此类推
 private static final int BEGIN_STATUS = 0;//初始状态全都在左岸
 private static final int END_STATUS = 0x7F;//目的是都到右岸去
 private static final int SAILOR = (1 << LION_A) | (1 << TIGER_B) | (1 << TIGER_b) | (1 << WOLF_C);
 private static Vector<Integer> stepVec = new Vector<Integer>();//存放摆渡的步骤,用于最后输出步骤
   
    //存放每个场景可能的下一步场景
    //考虑到一共有6兽1船共7个物体,每个物体有左岸和右岸两个状态,因此一共有2的7次方共128个场景。
    //每个场景的下一步,仅有数种可能的场景:如AaBb|0   |Cc的下一步中,仅有Aa|  0|BbCc和Bb|  0|AaCc这两个合法的场景
    //利用这张表,可以方便的预测出下一步可能的动作,从而进行推演
 private static Vector<Integer>[] traceMap = createTraceMap();

 //创建traceMap
 private static Vector<Integer>[] createTraceMap(){
  //建立场景表traceMap
  Vector<Integer>[] traceMapTmp = new Vector[1 << TOTAL_STATUS];
  //int iCount = 0;
  for(int i = 0; i < (1 << TOTAL_STATUS); i++){
   traceMapTmp[i] = new Vector<Integer>();
   if(!isStatusLegal(i)){//如果当前状态不合法就不用再看了
    continue;
   }
   //printStatus(i);
   int statusTmp;
   if(isRight(i, SHIP)){//如果船在右岸
    for(int j = 1; j < TOTAL_STATUS; j++){
     if(isRight(i, j) && isSailor(j)){
      //决定划船的
      statusTmp = setLeft(setLeft(i, SHIP), j);
      if(isStatusLegal(statusTmp)){
       traceMapTmp[i].add(new Integer(statusTmp));
       //iCount++;
       //printStatus(statusTmp);
      }
      //决定是否带乘客
      int statusTmp2;
      for(int k = 1; k < TOTAL_STATUS; k++){
       if(isRight(statusTmp, k)){
        statusTmp2 = setLeft(statusTmp, k);
        if(isStatusLegal(statusTmp2)){
         traceMapTmp[i].add(new Integer(statusTmp2));
         //iCount++;
         //printStatus(statusTmp2);
        }
       }
      }
     }
    }
   } else {//如果船在左岸
    for(int j = 1; j < TOTAL_STATUS; j++){
     if(!isRight(i, j) && isSailor(j)){
      //决定划船的
      statusTmp = setRight(setRight(i, SHIP), j);
      if(isStatusLegal(statusTmp)){
       traceMapTmp[i].add(new Integer(statusTmp));
       //iCount++;
       //printStatus(statusTmp);
      }
      //决定是否带乘客
      int statusTmp2;
      for(int k = 1; k < TOTAL_STATUS; k++){
       if(!isRight(statusTmp, k)){
        statusTmp2 = setRight(statusTmp, k);
        if(isStatusLegal(statusTmp2)){
         traceMapTmp[i].add(new Integer(statusTmp2));
         //iCount++;
         //printStatus(statusTmp2);
        }
       }
      }
     }
    }
   }
   //System.out.println("\n");
  }
  //System.out.println("iCount = " + iCount);
  return traceMapTmp;
 }//end of createTraceMap
 
 //摆渡
 private static boolean goTowards(int status){
  //判断是否胜利了
  if(isSucceed(status)){
   stepVec.add(new Integer(status));
   return true;
  }
  if(stepVec.indexOf(status) == -1){//如果是之前没遇过的场景,可以继续走着看看
   stepVec.add(new Integer(status));
  }else{//如果转回了之前的场景,那就放弃这种走法
   return false;
  }
  for(int i = 0; i < traceMap[status].size(); i++){//穷举每个可能的下一步场景继续分析
   if(goTowards(traceMap[status].elementAt(i).intValue())){//递归深入 穷举
    return true;
   }
  }
  stepVec.remove(stepVec.size() - 1);//如果没找到
  return false;
 }
 
 //判断胜利条件
 private static boolean isSucceed(int status){
  return (status == END_STATUS) ? true : false;
 }
 //判断会不会划船的
 private static boolean isSailor(int animal){
  return (SAILOR & (1 << animal)) == (1 << animal);
 }
 //检查在status状态下,编号为animal的兽是否在右岸
 private static boolean isRight(int status, int animal){
  return (status & (1 << animal)) == (1 << animal);
 }
 //将某兽移动到左边
 private static int setLeft(int status, int animal){
  return status & ((~0)^(1 << animal));
 }
 //将某兽移动到右边
 private static int setRight(int status, int animal){
  return status | (1 << animal);
 }
 
 //判断当前情况是否有小兽成为牺牲品
 private static boolean isStatusLegal(int status){
  for(int i = 1; i < TOTAL_STATUS; i += 2){
   while(true){
    //如果父子不在同岸
    if(isRight(status, i)  ^ isRight(status, i + 1)){
     //那么另外两只大兽必须和父亲在同一边
     if((isRight(status, (i + 2) % 6) ^ isRight(status, i + 1))
        && (isRight(status, (i + 4) % 6) ^ isRight(status, i + 1))){
      break;
     }
     //否则小兽就挂了
     return false;
     
    //如果父子同岸,那么有大兽保护,小兽没问题
    }else {
     break;
    }
   }
  }
  return true;
 }
 
 //打印当前状态
 private static void printStatus(int status){
  StringBuffer strTmp = new StringBuffer("AaBbCc|0  0|AaBbCc");
  if(isRight(status, SHIP)){
   strTmp.replace(7, 8, " ");
  } else {
   strTmp.replace(10, 11, " ");
  }
  for(int i = 1; i < TOTAL_STATUS; i++){
   if(isRight(status, i)){
    strTmp.replace(i - 1, i, " ");
   } else {
    strTmp.replace(i + 11, i + 12, " ");
   }
  }
  System.out.println(strTmp);
 }
 
 //打印出步骤结果
 private static void showStep(){
  goTowards(BEGIN_STATUS);
  for(int i = 0; i < stepVec.size(); i++){
   printStatus(stepVec.elementAt(i).intValue());
  }
 }
 
 public static void main(String[] args) {
  showStep();
 }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值