#include <iostream>
#include <limits>
#include "ctime"
using namespace std;
const double DBL_MAX = numeric_limits<double>::max();
class Ant {
/**
* 蚂蚁爬行方向枚举值
*/
private:
const double LEFT = -1;
const double RIGHT = 1;
/**
* 蚂蚁所在位置,取值范围:[0,1]
*/
double position;
/**
* 蚂蚁当前爬行的方向
*/
double direction;
/**
* 蚂蚁爬行速度
*/
double speed = 1;
/**
* 蚂蚁已爬行的时长
*/
double crawlingTime = 0;
/**
* 蚂蚁距离下一次碰到其他蚂蚁的时间
*/
double nextMeetingTime = DBL_MAX;
/**
* 蚂蚁是否已离开木杆
*/
bool left = false;
public:
/**
* 控制蚂蚁调头
*/
void turnRound() {
direction *= -1;
}
/**
* 当蚂蚁不再会跟任何蚂蚁相遇时,控制蚂蚁直接离开木杆
*/
void leave() {
if (direction == LEFT) {
crawlingTime += position / speed;
} else {
crawlingTime += (1 - position) / speed;
}
nextMeetingTime = DBL_MAX;
left = true;
}
/**
* 控制蚂蚁爬行一段时间(前提在此段时间内不会和任何蚂蚁相遇)
*
* @param time
* 控制蚂蚁爬行的时间
*/
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 = DBL_MAX;
}
/**
* 计算和另一只蚂蚁相遇的时间
*
* @param ant
* 另一只蚂蚁
* @return 和另一只蚂蚁相遇的时间
*/
double timeToMeet(Ant ant) {
if (direction * ant.getDirection() > 0) {
return DBL_MAX;
}
if ((direction == LEFT && getPosition() <= ant.getPosition())
|| (direction == RIGHT && getPosition() >= ant.getPosition()) ){
return DBL_MAX;
}
return (getPosition() + ant.getPosition() ) * 0.5;
}
double getCrawlingTime() {
return this->crawlingTime;
}
void setCrawlingTime(double crawlingTime) {
this->crawlingTime = crawlingTime;
}
bool isLeft() {
return this->left;
}
void setLeft(bool left) {
this->left = left;
}
double getPosition() {
return this->position;
}
void setPosition(double position) {
this->position = position;
}
double getDirection() {
return this->direction;
}
void setDirection(double direction) {
this->direction = direction;
}
double getSpeed() {
return this->speed;
}
void setSpeed(double speed) {
this->speed = speed;
}
double getNextMeetingTime() {
return this->nextMeetingTime;
}
void setNextMeetingTime(double nextMeetingTime) {
this->nextMeetingTime = nextMeetingTime;
}
};
double allAntsLeftTime(Ant *ants[]);
void crawling(Ant *ants[], double time);
double nextMeeting(Ant *ants[]);
const int ANT_SIZE = 20;
/**
* 计算所有蚂蚁离开木杆的耗时
*
* @param ants 所有蚂蚁
* @return 所有蚂蚁离开木杆的耗时
*/
double allAntsLeftTime(Ant *ants[])
{
double nextMeetingTime;
// 若木杆上的蚂蚁可能相遇,则控制蚂蚁持续爬行,直至不会再出现蚂蚁相遇
while((nextMeetingTime = nextMeeting(ants)) < DBL_MAX)
{
crawling(ants, nextMeetingTime);
}
double maxCrawlingTime = 0;
// 遍历蚂蚁在木杆上爬行的时间,获取最大值,即为所有蚂蚁离开木杆的时间
for(int i = 0; i < ANT_SIZE; i++)
{
// 若蚂蚁还未离开木杆,控制其离开
if(!ants[i]->isLeft())
{
ants[i]->leave();
}
if( ants[i]->getCrawlingTime() > maxCrawlingTime)
{
maxCrawlingTime = ants[i]->getCrawlingTime();
}
}
return maxCrawlingTime;
}
/**
* 控制所有蚂蚁爬行一段时间(前提:在这个时间段内,所有蚂蚁都不会相遇)
*
* @param ants 所有蚂蚁
* @param time 爬行时间
*/
void crawling(Ant *ants[], double time)
{
for(int i = 0; i < ANT_SIZE; i++)
{
if(ants[i]->isLeft())
{
continue;
}
// 若当前蚂蚁不会再和任何蚂蚁相遇,控制其离开,计算爬行时间
if(ants[i]->getNextMeetingTime() == DBL_MAX)
{
ants[i]->leave();
continue;
}
ants[i]->crawling(time);
if(ants[i]->getNextMeetingTime() == time)
{
ants[i]->turnRound();
}
}
}
/**
* 计算下一次出现蚂蚁相遇事件的时间
*
* @param ants 所有蚂蚁
* @return 下一次出现蚂蚁相遇事件的时间
*/
double nextMeeting(Ant *ants[]) {
Ant *ant1, *ant2;
double timeToMeet;
// 计算每只蚂蚁与其他蚂蚁相遇的最短时间
// 已离开木杆的蚂蚁不会再和任何蚂蚁相遇
for (int i = 0; i < ANT_SIZE; i++) {
ant1 = ants[i];
// 若蚂蚁1已离开木杆,则无需计算
if(ant1->isLeft())
{
continue;
}
// 计算蚂蚁1与其他蚂蚁相遇的最短时间
for (int j = i + 1; j < ANT_SIZE; j++) {
ant2 = ants[j];
// 若蚂蚁2已离开木杆,则无需计算
if(ant2->isLeft())
{
continue;
}
timeToMeet = ant1->timeToMeet(*ant2);
if (timeToMeet == DBL_MAX) {
continue;
}
// 若两只蚂蚁可以相遇,且相遇时间短于当前最小时间,则刷新起下次相遇时间
if (ant1->getNextMeetingTime() > timeToMeet) {
ant1->setNextMeetingTime(timeToMeet);
}
if (ant2->getNextMeetingTime() > timeToMeet) {
ant2->setNextMeetingTime(timeToMeet);
}
}
}
// 获取下一次出现蚂蚁相遇的时间点(发生在多久以后)
double nextMeetTime = DBL_MAX;
for(int i = 0; i < ANT_SIZE; i++)
{
if(ants[i]->getNextMeetingTime() < nextMeetTime)
{
nextMeetTime = ants[i]->getNextMeetingTime();
}
}
return nextMeetTime;
}
int main()
{
cout << "Hello world!" << endl;
Ant *ants[ANT_SIZE];
double leftTime;
double maxLeftTime = 0;
srand(time(NULL));
for(int t = 0; t < 100; t++)
{
for(int i = 0; i < ANT_SIZE; i++)
{
ants[i] = new Ant();
ants[i]->setPosition(((double)rand()/RAND_MAX));
ants[i]->setDirection(((double)rand()/RAND_MAX) > 0.5 ? 1 : -1);
}
leftTime = allAntsLeftTime(ants) * 2; //一只蚂蚁爬完木杆耗时2分钟
printf("All Ants Left Time: %f\r\n", leftTime);
if(maxLeftTime < leftTime)
{
maxLeftTime = leftTime;
}
}
printf("Max Left Time: %f\r\n", maxLeftTime);
return 0;
}