騰訊面試題——螞蟻爬行(C++版)
阿新 • • 發佈:2018-12-10
#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; }