腾讯面试题——蚂蚁爬行(C++版)

#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;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值