百度面试题-蚂蚁过木板-完整解答

最近在准备校招的事情,顺便做一下各名企的笔试题,题还是挺有意思的,下面是百度的一道典型笔试题解答。


1
题目:有一根27厘米的细木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置上各有一只蚂蚁。木杆很细,不能同时通过一只蚂蚁。开始时,蚂蚁的头朝左还是朝右是任意的,它们只会朝前走或调头,但不会后退。当任意两只蚂蚁碰头时,两只蚂蚁会同时调头朝反方向走。假设蚂蚁们每秒钟可以走一厘米的距离。编写程序,求所有蚂蚁都离开木杆的最小时间和最大时间。

答案为:最小为11秒,最大为24秒。


该问题主要考查问题分析能力、编程能力,更侧重编程能力。

一、分析方面

    很显然是求最小距离和最大距离的问题,只不过中间带有行走的碰撞后调整方向,加大了复杂度。

    分析到此为止,其实就可以了。只要考虑如何把变化可能性程序化去计算就可以了。

二、编程方面

    前后我试着分析了3小时左右吧,其实最后也没分析清楚,当我动手编程的时候,很快就有思路,整个实现、测试、优化用了20分钟左右,就全部搞定了。有些时候,只靠单纯分析,不如边分析边实现,反而会事办功倍。下面附上全部代码,共2个类,约200行代码:

(1)面向对象编程之蚂蚁类的封装Ant.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package   pojos;
  
public   class   Ant {
  @Override
  public   String toString() {
   return   "Ant [direction="   + direction +  ", extra_x_postion="
     + extra_x_postion +  ", speed="   + speed +  ", under_x_postion="
     + under_x_postion +  ", x_position="   + x_position +  "]" ;
  }
  
  private   int   speed; // 无符号整型,其方向速度由自身值*direction来决定正反方向
  
  public   int   getSpeed() {
   return   speed;
  }
  
  public   int   getDirection() {
   return   direction;
  }
  
  public   void   setDirection( int   direction) {
   this .direction = direction;
  }
  
  public   void   setSpeed( int   speed) {
   this .speed = speed;
  }
  
  public   int   getX_position() {
   return   x_position;
  }
  
  public   void   setX_position( int   xPosition) {
   x_position = xPosition;
  }
  
  public   int   getUnder_x_postion() {
   return   under_x_postion;
  }
  
  public   void   setUnder_x_postion( int   underXPostion) {
   under_x_postion = underXPostion;
  }
  
  public   int   getExtra_x_postion() {
   return   extra_x_postion;
  }
  
  public   void   setExtra_x_postion( int   extraXPostion) {
   extra_x_postion = extraXPostion;
  }
  
  private   int   direction; // 正反,+1,-1
  private   int   x_position;
  
  private   int   under_x_postion;
  private   int   extra_x_postion;
  
  public   Ant( int   speed, int   x_position,  int   under_x_postion,  int   extra_x_postion) {
   this .speed = speed;
   this .x_position=x_position;
   this .under_x_postion = under_x_postion;
   this .extra_x_postion = extra_x_postion;
  }
  
  public   boolean   isOut() {
   if   (x_position <=  this .under_x_postion
     || x_position >=  this .extra_x_postion) {
    return   true ;
   else   {
    return   false ;
   }
  }
  public   void   runOnce(){
   this .x_position= this .x_position+ this .speed* this .direction;
  }
   
}

 

 

(2) 面向对象编程之业务处理类的封装,也包括了main方法中的测试代码段

 
 

package test;

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

import pojos.Ant;

public class TestAntOutQuestion {
 public static int directionList[][] = null;
 public static int time_size = 0;
 public static int all_ant_num = 0;// 每次比较的起始方向值,只有+1,-1,代表正反两方向
 public static List<Integer> x_position_list = null;

 public static List<Ant> remove_ant_list = new ArrayList<Ant>();

 //计算初始化
 public static void init(List<Integer> init_x_position_list) {
  System.out.println("蚂蚁个数为---" + init_x_position_list.size());
  System.out.println("初始位置序列为---" + init_x_position_list);

  x_position_list = init_x_position_list;

  int ant_num = x_position_list.size();
  all_ant_num = ant_num;

  int sum_time = 1;
  for (int i = 0; i < ant_num; i++) {
   sum_time *= 2;
  }
  directionList = new int[sum_time][ant_num];
  time_size = directionList.length;// 32次
  // ant_num = directionList[0].length;// 每次比较的起始方向值,只有+1,-1,代表正反两方向

  String temp = null;// 存放0-31的二进制数
  char char_array[] = null;// 存放打散的int集合

  for (int i = 0; i < time_size; i++) {
   temp = getFixString(ant_num, i);
   char_array = temp.toCharArray();

   int arr_len = char_array.length;
   for (int j = 0; j < arr_len; j++) {
    if (char_array[j] == '0') {
     directionList[i][j] = -1;
    } else {
     directionList[i][j] = 1;
    }
   }
  }
 }

 // 得到最小用时
 public static int getMinTime(int unsign_speed, int under_x_postion,
   int extra_x_postion) {
  List<Integer> list = getAllTime(unsign_speed, under_x_postion,
    extra_x_postion);
  Collections.sort(list);
  return list.get(0);
 }

 // 得到最大用时
 public static int getMaxTime(int unsign_speed, int under_x_postion,
   int extra_x_postion) {
  List<Integer> list = getAllTime(unsign_speed, under_x_postion,
    extra_x_postion);
  Collections.sort(list);
  return list.get(list.size() - 1);
 }

 // 得到所有情况下的用时
 public static List<Integer> getAllTime(int unsign_speed,
   int under_x_postion, int extra_x_postion) {
  List<Integer> timeList = new ArrayList<Integer>();// 存放最后的时间集合

  List<Ant> ant_list = new ArrayList<Ant>(5);// 存放每个节点的ant对象

  int temp_count = 0;
  // 给5个蚂蚁分别给方向值,共32个搭配
  for (int[] one_time : directionList) {// one_time.length=ant_num
   Ant ant_temp = null;
   for (int index = 0; index < all_ant_num; index++) {
    ant_temp = new Ant(unsign_speed, x_position_list.get(index),
      under_x_postion, extra_x_postion);
    ant_temp.setDirection(one_time[index]);
    ant_list.add(ant_temp);
   }

   int begin = 0;

   processConflict(ant_list);// 首先处理一次冲突

   while (!isEnd(ant_list)) {
    // System.out.println(ant_list);
    // 去除已经走出的ant
    removeOverAnt(ant_list);

    allRunOnce(ant_list);
    processConflict(ant_list);
    begin++;
   }

   temp_count++;
   timeList.add(begin);
   // System.out.println(begin);
  }
  return timeList;
 }

 /**
  * 判断所有的蚂蚁是否都已经离开
  * 
  * @param antList
  * @return
  */
 public static boolean isEnd(List<Ant> antList) {
  boolean isExist = true;
  for (Ant ant : antList) {
   if (ant.isOut()) {
    remove_ant_list.add(ant);
   } else {
    isExist = false;
   }
  }
  return isExist;
 }
    /**
     * 删除掉所有的已经out的节点的ant
     * @param antList
     */
 public static void removeOverAnt(List<Ant> antList) {
  for (Ant ant : remove_ant_list) {
   antList.remove(ant);
  }
  remove_ant_list.clear();
 }

 /**
  * 所有ant均走1cm
  * @param antList
  */
 public static void allRunOnce(List<Ant> antList) {
  for (Ant ant : antList) {
   ant.runOnce();
  }
 }

 /**
  * 处理冲突,若有则处理没有则算了 只会出现两两的冲突,不会有两个以上的 ant同时发生冲突
  * 解决完一次冲突后,有可能会产生次生冲突,故要循环节点集合是否产生冲突,直到集合都无任何冲突则该向方法执行完成
  * @param antList
  */
 public static void processConflict(List<Ant> antList) {
  int len = antList.size();
  while (isFindConflict(antList)) {// 循环处理冲突,直到没有任何的conflict
   for (int i = 0; i < len - 1; i++) {
    if (isConflict(antList.get(i), antList.get(i + 1))) {
     solveConflict(antList.get(i), antList.get(i + 1));
    }
   }
  }
 }

 // 发现节点集合中是否有冲突产生
 public static boolean isFindConflict(List<Ant> antList) {
  int len = antList.size();
  for (int i = 0; i < len - 1; i++) {
   if (isConflict(antList.get(i), antList.get(i + 1))) {
    return true;
   }
  }
  return false;
 }

 // 解决两ant冲突,直接变向
 public static void solveConflict(Ant ant_1, Ant ant_2) {
  ant_1.setDirection(ant_1.getDirection() * -1);
  ant_2.setDirection(ant_2.getDirection() * -1);
 }

 // 判断两ant是否冲突,1是要对向,2是两者x_postion+this.speed*this.direction有交叉处
 public static boolean isConflict(Ant ant_1, Ant ant_2) {
  if ((ant_1.getDirection() != ant_2.getDirection())
    && ((ant_1.getX_position() + ant_1.getSpeed()
      * ant_1.getDirection() == ant_2.getX_position()) || (ant_2
      .getX_position()
      + ant_2.getSpeed() * ant_2.getDirection() == ant_1
      .getX_position()))) {
   return true;
  }
  return false;
 }

 // 得到指len相应的数字的二进制字符串表示形式
 public static String getFixString(int fix_length, int value) {
  String temp = Integer.toBinaryString(value);
  int temp_len = temp.length();
  for (int i = temp_len; i < fix_length; i++) {
   temp = "0" + temp;
  }
  return temp;
 }

 public static void main(String[] args) {
  // 给出初始状态位置集合
  List<Integer> x_position_list = new ArrayList<Integer>();
  x_position_list.add(3);
  x_position_list.add(7);
  x_position_list.add(11);
  x_position_list.add(17);
  x_position_list.add(23);
  // //>5的部分了
//   x_position_list.add(12);
  // x_position_list.add(13);
  // x_position_list.add(14);
  // x_position_list.add(15);
   x_position_list.add(25);
   x_position_list.add(24);
//   x_position_list.add(26);

  Collections.sort(x_position_list);// 先排下序
  init(x_position_list);

  int all_length=27;
  System.out.println("min time---" + getMinTime(1, 0, all_length));
  System.out.println("max time---" + getMaxTime(1, 0, all_length));
 }
}

希望对后来的同学们有帮助。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值