5个钢珠离开凹轨的最短时间和最长时间

题目

在一个长为33厘米的光滑凹轨上,在第3厘米、第6厘米、第19厘米、第22厘米、第26厘米处各有一个钢珠,凹轨很细,不能同时通过两个钢珠,开始时,钢珠运动方向是任意的。两个钢珠相撞后,以相同速度反向运动。假设所有钢珠初始速度为每秒运动1厘米,那么所有钢珠离开凹轨的最短和最长时间是多少? 

分析

钢珠不同方向组合

钢珠的方向是任意的,可以为左,也可以为右,所以总共有2的5次方种可能,也就是32种~

	/**
	 * 
	 * 
	 * 可以从0~31来遍历,初始化钢珠的开始位置 0代码向左,1代码向右。
	 * 
	 */
	private Direction[] initialDirections(int value) {

		int[] result = new int[5];
		result[0] = value % 2;
		result[1] = value / 2 % 2;
		result[2] = value / 4 % 2;
		result[3] = value / 8 % 2;
		result[4] = value / 16 % 2;
		Direction[] directions = new Direction[result.length];
		for (int i = 0; i < result.length; i++) {
			if (0 == result[i]) {
				directions[i] = Direction.LEFT;
			} else {
				directions[i] = Direction.RIGHT;
			}
		}
		return directions;

	}

单个钢珠完成的条件

单个钢珠完成的条件为要么到最左边或者最右边,从而脱离轨道~

			/**
			 * 
			 * 在一个长为33厘米的光滑凹轨上,在第3厘米、第6厘米、第19厘米、第22厘米、第26厘米处各有一个钢珠,
			 * 
			 */
			if (location <= 0 || location >= 33) {
				completed = true;
			}

所有钢珠完成的条件

	/**
	 * 
	 * 判断所有的钢球是否都离开凹轨
	 * 
	 */
	private boolean isAllBallsCompleted(Ball[] Balls) {

		for (Ball Ball : Balls) {
			if (!Ball.isCompleted()) {
				return false;
			}
		}
		return true;
	}

方向枚举


/**
 * 方向枚举类
 * 
 * @author wangmengjun
 *
 */
public enum Direction {
	
	RIGHT, LEFT;

	public boolean isRight() {
		return RIGHT == this;
	}

	public boolean isLeft() {
		return LEFT == this;
	}
}

钢珠类


/**
 * 钢珠球类
 * 
 * @author wangmengjun
 *
 */
public class Ball {

	/** 钢球所在的位置 */
	private int location;

	/** 钢球移动的方向 */
	private Direction direction;

	/** 钢球是否已经滚落凹轨 */
	private boolean completed = false;

	public Ball() {
	}

	public Ball(int location, Direction direction) {
		this.location = location;
		this.direction = direction;
	}

	/**
	 * 
	 * 钢球移动
	 * 
	 */
	public void move() {
		if (!completed) {
			if (direction.isRight()) {
				location += 1;
			} else if (direction.isLeft()) {
				location -= 1;

			}

			/**
			 * 
			 * 在一个长为33厘米的光滑凹轨上,在第3厘米、第6厘米、第19厘米、第22厘米、第26厘米处各有一个钢珠,
			 * 
			 */
			if (location <= 0 || location >= 33) {
				completed = true;
			}
		}
	}

	/**
	 * 
	 * 判断钢球的位置是否有冲突。
	 * 
	 */
	public boolean isLocationConfilict(Ball ball) {
		return this.location == ball.location;
	}

	/**
	 * 
	 * 当钢球位置冲突的时候,需要转换钢球的方向。
	 * 
	 */
	public void changeDirection() {
		switch (direction) {
		case RIGHT:
			direction = Direction.LEFT;
			break;
		case LEFT:
			direction = Direction.RIGHT;
			break;
		default:
			break;
		}
	}

	/**
	 * @return the location
	 */
	public int getLocation() {
		return location;
	}

	/**
	 * @param location
	 *            the location to set
	 */
	public void setLocation(int location) {
		this.location = location;
	}

	/**
	 * @return the direction
	 */
	public Direction getDirection() {
		return direction;
	}

	/**
	 * @param direction
	 *            the direction to set
	 */
	public void setDirection(Direction direction) {
		this.direction = direction;
	}

	/**
	 * @return the completed
	 */
	public boolean isCompleted() {
		return completed;
	}

	/**
	 * @param completed
	 *            the completed to set
	 */
	public void setCompleted(boolean completed) {
		this.completed = completed;
	}

}

钢珠移动的场景类


/**
 * 钢球移动的场景类
 * 
 * <pre>
 * 在一个长为33厘米的光滑凹轨上,在第3厘米、第6厘米、第19厘米、第22厘米、第26厘米处各有一个钢珠,
 * 凹轨很细,不能同时通过两个钢珠,开始时,钢珠运动方向是任意的。两个钢珠相撞后,以相同速度反向运动。
 * 假设所有钢珠初始速度为每秒运动1厘米,那么所有钢珠离开凹轨的最短和最长时间是多少?
 * </pre>
 * 
 * @author wangmengjun
 */

public class BallMoveScene {

	/** 5只钢球的初始位置 */
	private static int[] locations = { 3, 6, 19, 22, 26 };

	private int minElapsedTime = 0;

	private int maxElapsedTime = 0;

	public void proceed() {
		/**
		 * 5个钢球初始方向有32种情况
		 */
		for (int i = 0; i < 32; i++) {
			Ball[] balls = buildInitializedBalls(initialDirections(i));
			printInitialDirections(balls, i);

			int elapsedTime = 0;
			while (!isAllBallsCompleted(balls)) {
				move(balls);
				handleLocationConfilict(balls);
				elapsedTime++;
			}

			System.out.println("-- 花费的时间是:" + elapsedTime);

			if (minElapsedTime == 0 || (elapsedTime < minElapsedTime)) {
				minElapsedTime = elapsedTime;
			}

			if (maxElapsedTime == 0 || (elapsedTime > maxElapsedTime)) {
				maxElapsedTime = elapsedTime;
			}
		}

		System.out.println("结果==>");
		System.out.println("最少时间是:" + minElapsedTime);
		System.out.println("最大时间是:" + maxElapsedTime);

	}

	/**
	 * 
	 * 输出第n种的钢珠初始化方向。
	 * 
	 */
	private void printInitialDirections(Ball[] balls, int n) {
		System.out.print("第" + (n + 1) + "种情况的初始方向是: ");
		for (Ball ball : balls) {
			System.out.print(ball.getDirection().isLeft() ? " Left " : " Right ");
		}

	}

	/**
	 * 
	 * 判断是否有钢珠位置冲突, 如果位置有冲突,那么这两只钢珠的方向将改变。
	 * 
	 */
	private void handleLocationConfilict(Ball[] balls) {
		for (int i = 0; i < balls.length; i++) {
			for (int j = i + 1; j < balls.length; j++) {
				if (balls[i].isLocationConfilict(balls[j])) {
					balls[i].changeDirection();
					balls[j].changeDirection();
				}
			}
		}
	}

	/**
	 * 
	 * 钢珠移动
	 * 
	 */
	private void move(Ball[] balls) {
		for (Ball ball : balls) {
			ball.move();
		}
	}

	/**
	 * 
	 * 5只钢珠,每只钢珠可以向左(朝0的方向走),也可以向右(朝27的方向走), 这样的话有2的5次方,也就是32种情况。
	 * 
	 * 可以从0~31来遍历,初始化钢珠的开始位置 0代码向左,1代码向右。
	 * 
	 */
	private Direction[] initialDirections(int value) {

		int[] result = new int[5];
		result[0] = value % 2;
		result[1] = value / 2 % 2;
		result[2] = value / 4 % 2;
		result[3] = value / 8 % 2;
		result[4] = value / 16 % 2;
		Direction[] directions = new Direction[result.length];
		for (int i = 0; i < result.length; i++) {
			if (0 == result[i]) {
				directions[i] = Direction.LEFT;
			} else {
				directions[i] = Direction.RIGHT;
			}
		}
		return directions;

	}

	/**
	 * 
	 * @param directions
	 * 
	 *            初始化的方向
	 * 
	 * @return 返回初始化5个钢球的最初状态,包括初始化的位置以及初始化的方向。
	 * 
	 */

	private Ball[] buildInitializedBalls(Direction[] directions) {

		Ball[] Balls = new Ball[5];
		for (int i = 0; i < 5; i++) {
			Balls[i] = new Ball(locations[i], directions[i]);
		}
		return Balls;

	}

	/**
	 * 
	 * 判断所有的钢球是否都离开凹轨
	 * 
	 */
	private boolean isAllBallsCompleted(Ball[] Balls) {

		for (Ball Ball : Balls) {
			if (!Ball.isCompleted()) {
				return false;
			}
		}
		return true;
	}

}

测试类

/**
 * 
 * @author wangmengjun
 *
 */
public class Main {

	public static void main(String[] args) {
		new BallMoveScene().proceed();
	}
}

测试结果~

第1种情况的初始方向是:  Left  Left  Left  Left  Left -- 花费的时间是:26
第2种情况的初始方向是:  Right  Left  Left  Left  Left -- 花费的时间是:30
第3种情况的初始方向是:  Left  Right  Left  Left  Left -- 花费的时间是:27
第4种情况的初始方向是:  Right  Right  Left  Left  Left -- 花费的时间是:30
第5种情况的初始方向是:  Left  Left  Right  Left  Left -- 花费的时间是:26
第6种情况的初始方向是:  Right  Left  Right  Left  Left -- 花费的时间是:30
第7种情况的初始方向是:  Left  Right  Right  Left  Left -- 花费的时间是:27
第8种情况的初始方向是:  Right  Right  Right  Left  Left -- 花费的时间是:30
第9种情况的初始方向是:  Left  Left  Left  Right  Left -- 花费的时间是:26
第10种情况的初始方向是:  Right  Left  Left  Right  Left -- 花费的时间是:30
第11种情况的初始方向是:  Left  Right  Left  Right  Left -- 花费的时间是:27
第12种情况的初始方向是:  Right  Right  Left  Right  Left -- 花费的时间是:30
第13种情况的初始方向是:  Left  Left  Right  Right  Left -- 花费的时间是:26
第14种情况的初始方向是:  Right  Left  Right  Right  Left -- 花费的时间是:30
第15种情况的初始方向是:  Left  Right  Right  Right  Left -- 花费的时间是:27
第16种情况的初始方向是:  Right  Right  Right  Right  Left -- 花费的时间是:30
第17种情况的初始方向是:  Left  Left  Left  Left  Right -- 花费的时间是:22
第18种情况的初始方向是:  Right  Left  Left  Left  Right -- 花费的时间是:30
第19种情况的初始方向是:  Left  Right  Left  Left  Right -- 花费的时间是:27
第20种情况的初始方向是:  Right  Right  Left  Left  Right -- 花费的时间是:30
第21种情况的初始方向是:  Left  Left  Right  Left  Right -- 花费的时间是:22
第22种情况的初始方向是:  Right  Left  Right  Left  Right -- 花费的时间是:30
第23种情况的初始方向是:  Left  Right  Right  Left  Right -- 花费的时间是:27
第24种情况的初始方向是:  Right  Right  Right  Left  Right -- 花费的时间是:30
第25种情况的初始方向是:  Left  Left  Left  Right  Right -- 花费的时间是:19
第26种情况的初始方向是:  Right  Left  Left  Right  Right -- 花费的时间是:30
第27种情况的初始方向是:  Left  Right  Left  Right  Right -- 花费的时间是:27
第28种情况的初始方向是:  Right  Right  Left  Right  Right -- 花费的时间是:30
第29种情况的初始方向是:  Left  Left  Right  Right  Right -- 花费的时间是:14
第30种情况的初始方向是:  Right  Left  Right  Right  Right -- 花费的时间是:30
第31种情况的初始方向是:  Left  Right  Right  Right  Right -- 花费的时间是:27
第32种情况的初始方向是:  Right  Right  Right  Right  Right -- 花费的时间是:30

结果==>
最少时间是:14
最大时间是:30

将上述的钢珠改成蚂蚁,还是一样的解法~ :)

转载于:https://my.oschina.net/wangmengjun/blog/868678

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值