/**
* 蚂蚁类,用于记录蚂蚁的状态及控制蚂蚁行为
*/
public class Ant {
/**
* 蚂蚁爬行方向枚举值
*/
public interface Direction {
/**
* 向左爬行
*/
double LEFT = -1;
/**
* 向右爬行
*/
double RIGHT = 1;
}
/**
* 蚂蚁所在位置,取值范围:[0,1]
*/
private double position;
/**
* 蚂蚁当前爬行的方向
*/
private double direction;
/**
* 蚂蚁爬行速度
*/
private double speed = 1;
/**
* 蚂蚁已爬行的时长
*/
private double crawlingTime;
/**
* 蚂蚁距离下一次碰到其他蚂蚁的时间
*/
private double nextMeetingTime = Double.MAX_VALUE;
/**
* 蚂蚁是否已离开木杆
*/
private boolean left = false;
/**
* 控制蚂蚁调头
*/
public void turnRound() {
this.direction *= -1;
}
/**
* 当蚂蚁不再会跟任何蚂蚁相遇时,控制蚂蚁直接离开木杆
*/
public void leave() {
if (this.direction == Direction.LEFT) {
crawlingTime += position / speed;
} else {
crawlingTime += (1 - position) / speed;
}
nextMeetingTime = Double.MAX_VALUE;
left = true;
}
/**
* 控制蚂蚁爬行一段时间(前提在此段时间内不会和任何蚂蚁相遇)
*
* @param time
* 控制蚂蚁爬行的时间
*/
public void crawling(double time) {
double lastPosition = position;
position += time * speed * direction;
// 若爬行结束时蚂蚁已离开木杆,则将其离开状态刷新为true
if (position < 0 || position > 1) {
left = true;
crawlingTime += (position < 0 ? lastPosition / speed : (lastPosition - 1) / speed);
}
crawlingTime += time;
nextMeetingTime = Double.MAX_VALUE;
}
/**
* 计算和另一只蚂蚁相遇的时间
*
* @param ant
* 另一只蚂蚁
* @return 和另一只蚂蚁相遇的时间
*/
public double timeToMeet(Ant ant) {
if (this.direction * ant.getDirection() > 0) {
return Double.MAX_VALUE;
}
if (this.direction == Direction.LEFT && this.getPosition() <= ant.getPosition()
|| this.direction == Direction.RIGHT && this.getPosition() >= ant.getPosition()) {
return Double.MAX_VALUE;
}
return (this.getPosition() + ant.getPosition() ) * 0.5;
}
public double getCrawlingTime() {
return crawlingTime;
}
public void setCrawlingTime(double crawlingTime) {
this.crawlingTime = crawlingTime;
}
public boolean isLeft() {
return left;
}
public void setLeft(boolean left) {
this.left = left;
}
public double getPosition() {
return position;
}
public void setPosition(double position) {
this.position = position;
}
public double getDirection() {
return direction;
}
public void setDirection(double direction) {
this.direction = direction;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public double getNextMeetingTime() {
return nextMeetingTime;
}
public void setNextMeetingTime(double nextMeetingTime) {
this.nextMeetingTime = nextMeetingTime;
}
}
/**
* 主程序
*/
public class Main {
private static Main self;
public static void main(String[] args) {
self = new Main();
int count = 20;
Listants;
double crawlingTime, maxCrawlingTime = 0;
for(int i = 0; i < 1000; i++)
{
ants = new ArrayList();
self.init(ants, count);
// 所有蚂蚁离开木杆的时间
crawlingTime = self.allAntsLeftTime(ants);
maxCrawlingTime = crawlingTime > maxCrawlingTime ? crawlingTime : maxCrawlingTime;
System.out.println("Crawling Time:" + (crawlingTime * 2));
}
System.out.println("Max Crawling Time:" + (maxCrawlingTime * 2));
}
/**
* 计算所有蚂蚁离开木杆的耗时
*
* @param ants 所有蚂蚁
* @return 所有蚂蚁离开木杆的耗时
*/
private double allAntsLeftTime(Listants)
{
double nextMeetingTime;
// 若木杆上的蚂蚁可能相遇,则控制蚂蚁持续爬行,直至不会再出现蚂蚁相遇
while((nextMeetingTime = nextMeeting(ants)) < Double.MAX_VALUE)
{
crawling(ants, nextMeetingTime);
}
double maxCrawlingTime = 0;
Ant ant;
// 遍历蚂蚁在木杆上爬行的时间,获取最大值,即为所有蚂蚁离开木杆的时间
for(int i = 0; i < ants.size(); i++)
{
ant = ants.get(i);
// 若蚂蚁还未离开木杆,控制其离开
if(!ant.isLeft())
{
ant.leave();
}
if( ant.getCrawlingTime() > maxCrawlingTime)
{
maxCrawlingTime = ant.getCrawlingTime();
}
}
return maxCrawlingTime;
}
/**
* 控制所有蚂蚁爬行一段时间(前提:在这个时间段内,所有蚂蚁都不会相遇)
*
* @param ants 所有蚂蚁
* @param time 爬行时间
*/
private void crawling(Listants, double time)
{
Ant ant;
for(int i = 0; i < ants.size(); i++)
{
ant = ants.get(i);
if(ant.isLeft())
{
continue;
}
// 若当前蚂蚁不会再和任何蚂蚁相遇,控制其离开,计算爬行时间
if(ant.getNextMeetingTime() == Double.MAX_VALUE)
{
ant.leave();
continue;
}
ant.crawling(time);
if(ant.getNextMeetingTime() == time)
{
ant.turnRound();
}
}
}
/**
* 计算下一次出现蚂蚁相遇事件的时间
*
* @param ants 所有蚂蚁
* @return 下一次出现蚂蚁相遇事件的时间
*/
private double nextMeeting(Listants) {
Ant ant1, ant2;
double timeToMeet;
// 计算每只蚂蚁与其他蚂蚁相遇的最短时间
// 已离开木杆的蚂蚁不会再和任何蚂蚁相遇
for (int i = 0; i < ants.size(); i++) {
ant1 = ants.get(i);
// 若蚂蚁1已离开木杆,则无需计算
if(ant1.isLeft())
{
continue;
}
// 计算蚂蚁1与其他蚂蚁相遇的最短时间
for (int j = i + 1; j < ants.size(); j++) {
ant2 = ants.get(j);
// 若蚂蚁2已离开木杆,则无需计算
if(ant2.isLeft())
{
continue;
}
timeToMeet = ant1.timeToMeet(ant2);
if (timeToMeet == Double.MAX_VALUE) {
continue;
}
// 若两只蚂蚁可以相遇,且相遇时间短于当前最小时间,则刷新起下次相遇时间
if (ant1.getNextMeetingTime() > timeToMeet) {
ant1.setNextMeetingTime(timeToMeet);
}
if (ant2.getNextMeetingTime() > timeToMeet) {
ant2.setNextMeetingTime(timeToMeet);
}
}
}
// 获取下一次出现蚂蚁相遇的时间点(发生在多久以后)
double nextMeetTime = Double.MAX_VALUE;
for(int i = 0; i < ants.size(); i++)
{
if(ants.get(i).getNextMeetingTime() < nextMeetTime)
{
nextMeetTime = ants.get(i).getNextMeetingTime();
}
}
return nextMeetTime;
}
/**
* 初始化所有蚂蚁的状态
*
* @param ants 蚂蚁对象数组
* @param count 蚂蚁数量
*/
private void init(Listants, int count) {
Ant ant;
for (int i = 0; i < count; i++) {
ant = new Ant();
ant.setPosition(Math.random());
ant.setDirection((Math.random() > 0.5 ? 1 : -1));
ants.add(ant);
}
}
}