我正在从竞争中解决这个问题。我将在这里简要描述这个问题。
厨师正试图在时间T之前到达会议,但他希望以最少的等候时间在巴士站进行。除非他在T之前到达目的地并且在巴士站等候最少,否则他不介意选择长路线。他从1号站开始,目的地是最后一站。这是输入规范......
N T M
U V S E
U V S E
... and so on
其中N是站点数,T是会议时间,M是总线数。接下来的M行是公交车的详细信息。 U是公共汽车开始的地方,V是公共汽车到达的地方。 S是起始时间,E是到达时间。因此,总线在车站U开始,在时间S,并在时间E到达车站V.
Constraints
2 ≤ N ≤ 50000
1 ≤ T ≤ 109
1 ≤ M ≤ 100000 (105)
1 ≤ U ≤ N
1 ≤ V ≤ N
U ≠ V
0 ≤ S < E ≤ 10
这是我尝试过的,在代码之后和代码中进行了解释。
public int findMax(int nextStation, int rcd, int start, int end) {
int tt = start - rcd;
// If we reached destinaion, i.e the last station
// no more wait has to be done and we return the time
// required to reach here
if (nextStation == noOfStations) {
return tt;
}
// TODO : we already found a better path, so we skip this one
// if (tt > minTillNow) {
// return Integer.MAX_VALUE;
// }
List<Bus> buses = stations.get(nextStation);
// If we have not reached finalStation
// and there are no more buses from this station,
// we reached a dead end.
if (buses == null) {
return -1;
}
int temp, min = Integer.MAX_VALUE;
// If there are buses from this station, we try all
// of them
for (int i = 0; i < buses.size(); i++) {
temp = findMax(buses.get(i).v, end, buses.get(i).s, buses.get(i).e);
// Find minimum wait-time
if (temp != -1 && temp < min) {
min = temp;
}
}
// If no subtree has a path
if (min == Integer.MAX_VALUE) return -1;
// if the wait to reach here is greater than any subsequent
else if (min < tt) return tt;
else
return min;
}
我正在做一个DFS,从第一个站开始,沿着任何路径找到最大等待时间直到结束,然后选择沿这些路径的所有等待时间的最小值。这适用于给定的输入示例..
Input:
5 10 5
1 2 1 2
1 5 3 4
2 4 4 5
2 5 5 6
4 5 6 7
Output:
2
但是当我提交一些测试输入时出现“错误答案”而失败。 有人可以通过上述方法发现问题吗?这也是一般的好方法吗?这会是什么复杂性?我认为它应该是M线性的,是正确的逼近。
答案 0 :(得分:1)
我认为您忘记的是测试您是否仍然可以在for
循环中捕获总线(如下面的示例所示)。
除此之外,我认为你的代码比需要的更复杂。首先,-1
对“无路径”进行编码并不是很方便,因为在评估最短等待时间时需要额外的测试(我假设如果没有路径则必须返回-1
,但你最终可以处理这个问题。)
我会提出以下功能(并为N
和T
引入了新名称,但我认为它们足够有意义。)
public int minWaitingTime(int currentStop, int currentTime, int waitingTime) {
if (currentStop == destination) {
// reached the destination, return waitingTime if we met the deadline,
// or 'infinity' otherwise
// NOTE: I assumed currentTime <= deadline is ok, maybe that should be <
return currentTime <= deadline ? waitingTime : Integer.MAX_VALUE;
} else {
List<Bus> buses = stations.get(currentStop);
int min = Integer.MAX_VALUE;
for (Bus bus : buses) {
// test if we can still catch this bus
if (bus.s <= currentTime) {
// update minimum
min = Math.min(min,
minWaitingTime(bus.v, bus.e,
waitingTime + (bus.s - currentTime));
}
}
return min;
}
}
您现在可以将其称为:
public int findMinWaitingTime() {
int min = minWaitingTime(1, 0, 0);
return min == Integer.MAX_VALUE ? -1 : min;
}
是的,我希望这是一场古老的比赛,我现在不是在写你的解决方案......
答案 1 :(得分:1)
这看起来像Google Code Jam问题。您可以在他们的网站上找到其他人所做的解决方案。
使用深度优先搜索的问题在于它具有几何上增加的复杂性。因此,例如,如果每个站有10个站点和10个连接,则有10 ^ 10个路径,这些路径是数十亿。这就像试图蛮力解决国际象棋。
这种问题可以通过动态编程解决(Code Jam喜欢DP问题)。你之所以知道这一点,是因为任何一个站点的最佳移动都与你之前的站点无关。从最后一站向后解决问题。您将始终能够以这种方式找到任何特定移动的最短等待时间。
唯一的障碍是最小等待时间路径可能会在T之后到达。
要解决此问题,您应该在最小等待路径上进行回溯搜索。换句话说,您像以前一样执行DP解决方案,但要记录花费的总时间。如果它超过T,则回溯到上一个节点并继续从那里搜索。