问题:在一个长为33厘米的光滑凹轨上,在第3厘米、第6厘米、第19厘米、第22厘米、第26厘米处各有一个钢珠,凹轨很细,不能同时通过两个钢珠,开始时,钢珠运动方向是任意的。两个钢珠相撞后,以相同速度反向运动。假设所有钢珠初始速度为每秒运动1厘米,那么所有钢珠离开凹轨的最短和最长时间是多少?
分析:5个钢珠的移动方向都有两种可能:向左或者向右。这样钢珠运动的组合就有2的5次方,也就是32种。
最少时间是:14
最大时间是:30
第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
//方向枚举类
public enum Direction {
RIGHT, LEFT;
public boolean isRight() {
return RIGHT == this;
}
public boolean isLeft() {
return LEFT == this;
}
}
//钢珠球类
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 ant) {
return this.location == ant.location;
}
/**
*
* 当钢球位置冲突的时候,需要转换钢球的方向。
*
*/
public void changeDirection() {
switch (direction) {
case RIGHT:
direction = Direction.LEFT;
break;
case LEFT:
direction = Direction.RIGHT;
break;
default:
break;
}
}
/**
*
* @return the completed
*
*/
public boolean isCompleted() {
return completed;
}
/**
*
* @param completed
*
* the completed to set
*
*/
public void setCompleted(boolean completed) {
this.completed = completed;
}
/**
*
* @return the direction
*
*/
public Direction getDirection() {
return direction;
}
/**
*
* @param direction
*
* the direction to set
*
*/
public void setDirection(Direction direction) {
this.direction = direction;
}
/**
*
* @return the location
*
*/
public int getLocation() {
return location;
}
/**
*
* @param location
*
* the location to set
*
*/
public void setLocation(int location) {
this.location = location;
}
}
//钢球移动的场景类
/**
* 在一个长为33厘米的光滑凹轨上,在第3厘米、第6厘米、第19厘米、第22厘米、第26厘米处各有一个钢珠,
* 凹轨很细,不能同时通过两个钢珠,开始时,钢珠运动方向是任意的。两个钢珠相撞后,以相同速度反向运动。
* 假设所有钢珠初始速度为每秒运动1厘米,那么所有钢珠离开凹轨的最短和最长时间是多少?
*/
public class BallMoveScene {
/*
* 5只钢球的初始位置
*/
private static int[] locations = { 3, 6, 19, 22, 26 };
private int minElapsedTime = 0;
private int maxElapsedTime = 0;
public void proceed() {
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("最少时间是:" + 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;
}
}
//测试类
public class Test {
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