HighWay这一题描述如下:
给定一条高速公路,
在时间点为0时公路上停了N辆车,每辆车起始位置都不同,
首先输入一个整数N,2 <= N <= 1000.
接着输入N行,每一行格式为3个整数:X, Y and L,分别是一辆车的起始位置,离开位置以及速度。 0 <= X < Y <= 1000000, 0 < L <= 10.
因为高速公路只有一条车道,所以规定行驶在后面的车子不能超过行驶在它前面的车。
链接:http://hihocoder.com/contest/hiho65/problem/1
关于这题的解法,如果把它当做追及问题,就会变得非常非常复杂,我试了一下,感觉好像不是特别难,但是在写的时候遇到各种问题,真心不简单。
所以有大神提供了一种可以用动态规划来进行解决的思路:
http://hihocoder.com/discuss/question/2533
思路
class RunningCar
{
double start;
double end;
double speed;
double leavingTime;
...
};
For startPoint in sortedStarts from the rear
curCar = runningCars[startPoint];
For pos from curCar.start+1 to curCar.end
timeWithNoOvertaking = maxArrivingTime[pos-1] + 1.0/curCar.speed;
timeWithOvertaking = maxArrivingTime[pos];
maxArrivingTime[pos] = max( timeWithNoOvertaking, timeWithOvertaking);
End for
curCar.setLeavingTime(maxArrivingTime[curCar.end]);
End for
就上面这一小段,弄清楚了就很简单了。
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
bool isDebug = true;
class RunningCar
{
double start;
double end;
double speed;
double leavingTime;
public:
RunningCar()
{
start = end = 0;
speed = 0;
}
RunningCar(double start, double end, double speed)
{
this->start = start;
this->end = end;
this->speed = speed;
}
double getStart()
{
return start;
}
double getEnd()
{
return end;
}
double getSpeed()
{
return speed;
}
double getLeavingTime()
{
return leavingTime;
}
void setLeavingTime(double leavingTime)
{
this->leavingTime = leavingTime;
}
void display()
{
cout << "I am a car starts from " << start << " ends at " << end << " with the speed of " << speed << endl;
}
};
class HighWay
{
int N;
int maxEnd;
map<int, RunningCar *> runningCars;
vector<int> startPoints;
vector<int> sortedStarts;
double *maxArrivingTime;
public:
HighWay()
{
maxEnd = 0;
maxArrivingTime = NULL;
}
~HighWay()
{
if (maxArrivingTime != NULL)
{
delete[] maxArrivingTime;
maxArrivingTime = NULL;
}
runningCars.clear();
startPoints.clear();
sortedStarts.clear();
}
void readDataAndInitialize()
{
cin >> N;
for (int i = 0; i < N; i++)
{
int start, end, speed;
cin >> start >> end >> speed;
if (maxEnd < end)
maxEnd = end;
RunningCar *newCar = new RunningCar(start, end, speed);
runningCars[start] = newCar;
startPoints.push_back(start);
}
maxArrivingTime = new double[maxEnd+1];
for (int i = 0; i < maxEnd+1; i++)
maxArrivingTime[i] = 0;
sortedStarts = startPoints;
sort(sortedStarts.begin(), sortedStarts.end());
}
void calculateMaxLeavingTime()
{
int carsRunningAhead = sortedStarts.size();
while (carsRunningAhead > 0)
{
RunningCar *curCar = runningCars[sortedStarts[carsRunningAhead-1]];
calculateLeavingTimeForCar(curCar);
carsRunningAhead--;
}
}
private:
void calculateLeavingTimeForCar(RunningCar *curCar)
{
for (int i = curCar->getStart()+1; i <= curCar->getEnd(); i++)
{
calculateLeavingTimeForCarInPos(curCar, i);
}
curCar->setLeavingTime(maxArrivingTime[(int)curCar->getEnd()]);
if (isDebug)
{
printf("The car leaved at time %.2lf\n", curCar->getLeavingTime());
}
}
void calculateLeavingTimeForCarInPos(RunningCar *curCar, int pos)
{
double timeWithNoOvertaking = maxArrivingTime[pos-1] + 1.0/curCar->getSpeed();
maxArrivingTime[pos] = max(maxArrivingTime[pos], timeWithNoOvertaking);
if (isDebug)
{
printf("The car starts from %.0lf, ends at %.0lf, current pos at %d, time is %.2lf\n", curCar->getStart(), curCar->getEnd(), pos, maxArrivingTime[pos]);
}
}
public:
void showMaxArrivingTime()
{
for (int i = 0; i < maxEnd+1; i++)
{
cout << "The "<< i << "th max arriving time is " << maxArrivingTime[i] << endl;
}
}
void showLeavingTime()
{
for (int i = 0; i < startPoints.size(); i++)
{
RunningCar *curCar = runningCars[startPoints[i]];
//printf("%.2lf\n", maxArrivingTime[(int)curCar->getEnd()]);
printf("%.2lf\n", curCar->getLeavingTime());
}
}
};
int main()
{
HighWay highWay;
highWay.readDataAndInitialize();
highWay.calculateMaxLeavingTime();
//highWay.calculateLeavingTimeForCar(NULL);
if (isDebug)
highWay.showMaxArrivingTime();
highWay.showLeavingTime();
system("pause");
return 0;
}
计算某车在pos位置时的离开时间的分析:
void calculateLeavingTimeForCarInPos(RunningCar *curCar, int pos)
{
double timeWithNoOvertaking = maxArrivingTime[pos-1] + 1.0/curCar->getSpeed();
maxArrivingTime[pos] = max(maxArrivingTime[pos], timeWithNoOvertaking);
if (isDebug)
{
printf("The car starts from %.0lf, ends at %.0lf, current pos at %d, time is %.2lf\n", curCar->getStart(), curCar->getEnd(), pos, maxArrivingTime[pos]);
}
}
运行中遇到的问题
1.在代码重构的时候犯了一个错误,
我定义HighWay类,它里边有个成员变量为double *maxArrivingTime,
我在构造函数里边将它初始化为NULL。
接着在void readDataAndInitialize()函数里边我是为它分配空间并进行初始化,
当时写成了double *maxArrivingTime = new double[maxEnd+1];
for (int i = 0; i < maxEnd+1; i++)
maxArrivingTime[i] = 0;
这样就出错了,同名变量的问题,C++编译的时候不会提示错误,但运行的时候却是会出错的!
2.用示例是可以运行成功,但还是得自己也设计几个例子来测试下
比如如下运行示例:
4
1 5 4
3 6 3
4 5 2
5 8 1
我发现出问题了,所以用isDebug进行信息输出,原来是我最后输出结果的时候出了问题
//printf("%.2lf\n", maxArrivingTime[(int)curCar->getEnd()]);
printf("%.2lf\n", curCar->getLeavingTime());
重构前的代码
int main()
{
vector<int> startPoints;
map<int, RunningCar *> runningCars;
int N;
cin >> N;
int maxEnd = 0;
for (int i = 0; i < N; i++)
{
int start, end, speed;
cin >> start >> end >> speed;
if (maxEnd < end)
maxEnd = end;
RunningCar *newCar = new RunningCar(start, end, speed);
runningCars[start] = newCar;
startPoints.push_back(start);
}
double *maxArrivingTime = new double[maxEnd+1];
for (int i = 0; i < maxEnd+1; i++)
maxArrivingTime[i] = 0;
vector<int> sortedStarts(startPoints);
sort(sortedStarts.begin(), sortedStarts.end());
int carsRunningAhead = sortedStarts.size();
while (carsRunningAhead > 0)
{
RunningCar *curCar = runningCars[sortedStarts[carsRunningAhead-1]];
for (int i = curCar->getStart(); i <= curCar->getEnd(); i++)
{
double curCarArrivingHereTime = 0;
if (i >=1 && maxArrivingTime[i-1] != 0)
{
curCarArrivingHereTime = maxArrivingTime[i-1] + 1.0/curCar->getSpeed();
}
else
{
curCarArrivingHereTime = ((double)i-curCar->getStart())/curCar->getSpeed();
}
maxArrivingTime[i] = max(maxArrivingTime[i], curCarArrivingHereTime);
}
curCar->setLeavingTime(maxArrivingTime[(int)curCar->getEnd()]);
carsRunningAhead--;
}
for (int i = 0; i < startPoints.size(); i++)
{
RunningCar *curCar = runningCars[startPoints[i]];
//cout << "The "<< i << "th car leaved at " << maxArrivingTime[(int)curCar->getEnd()] << endl;
printf("%.2lf\n", maxArrivingTime[(int)curCar->getEnd()]);
}
cin >> N;
return 0;
}