Algorithm 如何实现竞赛模拟问题的解决方案

Algorithm 如何实现竞赛模拟问题的解决方案,algorithm,design-patterns,data-structures,Algorithm,Design Patterns,Data Structures,在一次采访中,有人问了一个问题: 在一级方程式挑战赛中,有n支队伍编号为1到n。每个队有一辆车和一名司机。车辆规格如下: 最高速度:(150+10*i)公里/小时 加速度:(2*i)米/秒平方 处理系数(hf)=0.8 Nitro:将速度增加到双倍或最高速度,以较小者为准。只能使用一次 这是我的队号。 汽车排着队参加比赛。第(i+1)辆车的起跑线在第i辆车后面200*i米处 他们都在同一时间开始,并试图达到他们的最高速度。每2秒钟对位置进行一次重新评估(因此,即使汽车已经越过了中间的终点线,

在一次采访中,有人问了一个问题:

在一级方程式挑战赛中,有n支队伍编号为1到n。每个队有一辆车和一名司机。车辆规格如下:

  • 最高速度:(150+10*i)公里/小时
  • 加速度:(2*i)米/秒平方
  • 处理系数(hf)=0.8
  • Nitro:将速度增加到双倍或最高速度,以较小者为准。只能使用一次
这是我的队号。 汽车排着队参加比赛。第(i+1)辆车的起跑线在第i辆车后面200*i米处

他们都在同一时间开始,并试图达到他们的最高速度。每2秒钟对位置进行一次重新评估(因此,即使汽车已经越过了中间的终点线,你也会在2秒钟后知道)。在此评估过程中,每位驾驶员都会检查其车10米范围内是否有任何车辆,其速度降低至:hf*(当时的速度)。此外,如果车手注意到自己是比赛的最后一名,他会使用“nitro”

以团队数量和赛道长度作为输入,计算最终速度和相应的完成时间

我不明白如何处理这种问题。对于每个实例,我应该检查每对驱动程序的所有组合并计算结果吗?但是我怎么才能知道我应该在什么情况下进行计算呢?

如果你检查一下,你会发现与种族问题有很多共同点

这是一个类比:

  • 初始状态(系统的种子):
    • 生命游戏:网格上的初始模式。具有以下参数的每个单元格:
      • x和y坐标
      • 细胞是活的还是死的
    • 比赛问题:n辆车,每辆车都有预定的参数和赛道长度l。每辆车都有以下参数:
      • 最高速度
      • 加速
      • 处理因子
      • 在轨道上的位置
      • 当前速度
  • 这些规则在称为滴答声的离散时刻应用。
    • 生命游戏:这些规则同时适用于上一代的每一个细胞,产生下一代。每一代都是前一代的纯函数
    • 比赛问题:规则同时适用于前一个州生产下一个州的每辆车。这种情况每2秒发生一次。和生命游戏一样,每一步都是前一步的纯函数,这意味着它只取决于前一状态下汽车的参数
不同的是,生命的游戏永远不会结束,而比赛问题应该在每辆车的当前位置大于或等于赛道长度l时终止(尽管最后一句话是有争议的:由于操纵因素,在某些情况下,有些车可能永远不会到达终点线)

关键点在于,计算是在离散时刻进行的,这回答了您的问题:

但是我怎么才能知道我应该在什么情况下进行计算呢

你可以借鉴本节的观点来解决这个问题。您需要有两个汽车数组:一个表示当前状态,另一个表示下一步。在每次迭代中,按照分配规则重新计算每辆车的当前位置和速度,并检查循环是否应终止。在下一次迭代之前,交换数组角色,以便上一次迭代中的后续数组成为下一次迭代中的当前数组

高级伪代码可能如下所示:

n = ..; // initial number of cars
l = ..; // track length
Car[] currentState = initializeState(n, l);
Car[] nextState = clone(currentState);
for (int iteration = 0; iteration < MAX_ITERATIONS; iteration++) {
    calculateNextState(currentState, nextState, iteration);
    swap(currentState, nextState);
    if (shouldTerminate(currentState, l) {
        break;
    }
}

printResultOrClaimNotTerminated(currentState);
哪个更好。排序后的汽车阵列自然会给你汽车的最后一个位置,你需要应用硝基增压规则。可能还有其他优化。这回答了你的问题:

对于每个实例,我应该检查每对驱动程序的所有C(n,2)组合并计算结果吗

汽车物体和游戏物体 我假设您已经为汽车创建了必要的对象,封装在游戏对象中

加快每个更新步骤以避免执行所有C(n,2)检查的想法 通过不必检查所有C(n,2)组合,可以加快更新位置和参数的步骤。您可以使用的一个简单的启发式方法是,我们不需要检查远处车辆之间的交互。例如,赛道第一季度的赛车不会与赛道第三季度的赛车交互。我想根据你问题的参数,你想把赛道分成10米长的部分。维护每个区段的列表,并跟踪每个区段中的所有车辆。更新位置后,仅检查连续区段中车辆之间的相互作用

同样,在每个更新步骤中跟踪哪辆车处于最后位置,并相应地切换助力器

时间步长的选择 在你的问题中,时间步长似乎固定为2秒。然而,在一般情况下,当你编写游戏时,这个选择是至关重要的。你可以玩几个不同的数字(例如10,50100500毫秒)

如果您选择的时间步长是一个更高的数字,(例如),汽车可能会通过另一辆汽车,从而避免检测到碰撞。
另一方面,如果您选择的时间步长太小,并且操作所花费的时间大于时间步长,则游戏将比实时运行慢。

我不确定,但如果我有您的问题,我认为您必须在“客户端-服务器”中实现model.you有一个服务器负责举行比赛。客户端是汽车(团队)。在每一步客户端告诉服务器他们的信息,服务器将其存储。他们可以访问所有其他汽车
O (n * log(n))