做出完整的圆形路径,最短路径运动?

时间:2011-11-15 11:19:39

标签: c# algorithm

我在接受采访时得到了这个问题而我无法解决。

  

你有一条环形公路,有N个加油站。你知道   每个车站都有的气体量。你知道你的气体量   需要从一个站转到下一个站。你的车从0开始   加油站。问题是:创建一个算法,以了解哪种气体   您必须开始驾驶以完成圆形路径。确实如此   未指定您必须访问所有电台。你只能开车   顺时针方向旋转。

我必须在c#

中这样做

我开始的唯一代码是GasStation实体

class GasStation
  int gasAtStation;
  int gasToMoveToNextStationNeeded;
  string nameOfGasStation;


GasTation wheretoStart(List<GasStation> list)
{

}

我是这样做的:

static void Main(string[] args)
        {
            int[] gasOnStation = {1, 2, 0, 4};
            int[] gasDrivingCostTonNextStation = {1, 1,2, 1};

            FindStartingPoint(gasOnStation, gasDrivingCostTonNextStation);

        }

        static void FindStartingPoint(int[] gasOnStation, int[] gasDrivingCosts)
        {
            // Assume gasOnStation.length == gasDrivingCosts.length
            int n = gasOnStation.Length;
            int[] gasEndValues = new int[n];
            int gasValue = 0;
            for (int i = 0; i < n; i++)
            {
                gasEndValues[i] = gasValue;
                gasValue += gasOnStation[i];
                gasValue -= gasDrivingCosts[i];
            }

            if (gasValue < 0)
            {
                Console.WriteLine("Instance does not have a solution");
                Console.ReadLine();
            }
            else
            {
                // Find the minimum in gasEndValues:
                int minI = 0;
                int minEndValue = gasEndValues[0];
                for (int i = 1; i < n; i++)
                {
                    if (gasEndValues[i] < minEndValue)
                    {
                        minI = i;
                        minEndValue = gasEndValues[i];
                    }
                }

                Console.WriteLine("Start at station: " + minI);
                Console.ReadLine();
            }
        }

由于

8 个答案:

答案 0 :(得分:5)

解决这个问题的一个简单方法是使用强力方法。即尝试每一个可能性并抛弃那些不起作用的东西。

即。依次从每个加油站开始(下面重复每个起始站)。

  • 有一个定义当前气体水平的变量。
  • 按顺时针顺序循环通过每个加油站。
    1. 加油(按加油站数量增加燃气)。
    2. 检查您是否可以转到下一站(gas >= gasToMoveToNextStationNeeded)
      • 如果没有,这不是解决方案,所以请转到下一个起始位置。
      • 如果是这样,减去使用的气体量,然后继续,直到你再次开始。
    3. 如果你回到起始加油站,你会有答案。

编辑按照@ Vash的回答,作为决定从哪里开始的改进,打折自己没有足够气体的车站到达下一站并按顺序开始工作气体量(下降)。


请注意,这假设我们访问所有加油站。如果您需要最佳解决方案,则需要改进跳过加油站(问题没有说明这一点)。

答案 1 :(得分:2)

这是@George Duckett回答的优化案例。

  • 选择并记住您的起始站。
  • 顺时针循环(1)到站。
    • 获取燃料。
    • 如果您有足够的燃油,请转到下一站,减少剩余燃油量,继续循环(1)

如果你到达了起始站 - 问题就解决了。

如果在某个电台上你没有足够的燃料来接下一个

  • 记住你的终点站。
  • Distance_to_start = 0,fuel_to_start = 0
  • 逆时针从启动站循环(2)。
    • 向您的柜台添加可用燃料和到下一站的距离
    • 如果fuel_to_start&gt; distance_to_start,你有一些多余的燃料。将此站标记为您的新开始并再次循环(1) - 可能您现在可以继续。
    • 否则,继续循环(2)

如果你逆时针走到已经访问过的车站 - 运气不好,车站上没有足够的燃料可以完全循环。

答案 2 :(得分:1)

任务真的很开放。当你进行一个循环时,最好的选择是从具有足够燃料量的站开始。这意味着您将能够驾驶汽车并开车到最近的车站。

当我们有一个起点时,我们只需要决定我们需要停哪个加油站。对于第一次运行,我们可以停止每个站。

编辑。

与Lasse V. Karlsen讨论后出现的小改进。

如果所选的第一个电台无法成功完成循环。然后以较小的*燃料/道路比例以相同的方式选择下一个。

*首先选择的比例小一些。

答案 3 :(得分:1)

制作电台的循环列表。 找到具有正值

的任何电台

Excess =(gasAtStation - gasToMoveToNextStationNeeded)

这是目前的基础。

当下一站具有负超额值时,将其gasAtStation和gasToMoveToNextStationNeeded添加到当前基本字段,并从列表中删除此站。

循环重复所有正站。

当没有更多的电台要删除时:

如果一个或一些非负站仍在列表中 - 其中任何一个都适合作为起点。

示例:

A(-50)B(100)C(-20)D(-90)E(60)[C-> B]

A(-50)B(80)D(-90)E(60)[D-> B]

A(-50)B(-10)E(60)[A-> E]

B(-10)E(10)[B-> E]

E(0)

答案 4 :(得分:1)

虽然尝试每个起始站当然工作正常,但它需要二次时间,而有一个简单的线性时间算法。

如果燃油油位达到负值,请使用可以继续行驶的魔车。从任意车站开始,进行全程旅行,参观每个车站。如果燃油量低于零,则没有解决方案。否则,启动的最佳站点是到达时的燃料水平最低的站点。

这是有效的,因为除了恒定的偏移之外,所有可能的旅行的燃料水平是相同的。

答案 5 :(得分:1)

如果我们定义从A站到B的行程包括GasAtStation A和TripCost。 然后,对于每次旅行,我们都有TripBalance = GasAtStation-TripCost

所有行程余额的总和必须大于或等于零,否则解决方案不存在。解决方案包括为每个加油站设置一个包含行程平衡的列表,并迭代保存tripBalance变量的项目,如果tripBalance变为负值,则行程应从下一个加油站开始,如果是,我们重置tripBalance我们继续处理,直到我们检查列表中的最后一个条目:

public int FindFirstStation(List<int> tripBalances)
{
  if (tripBalances.Sum() < 0) return -1;
  var firstStation = 0;
  var tripBalance = 0;

  for (int i = 0; i < tripBalances.Count; i++)
  {
    tripBalance += tripBalances[i];
    if (tripBalance < 0)
    {
      tripBalance = 0;
      firstStation = i + 1; // next station
    }
  }
  return firstStation;
}

我使用以下代码对其进行了测试:

[TestMethod]
public void Example()
{
  var tripBalances = new List<int> { 0, 1, -2, 3 };
  var resolver = new GasStationResolver();
  var indexOfGasStation = resolver.FindFirstStation(tripBalances);
  Assert.AreEqual(3, indexOfGasStation);
}

看到传递的值是问题标题中给出的示例中的值。在这种情况下,答案是我们列表中的最后一个加油站应该是第一个加油站。最后,如果没有解决方案,则该方法返回-1。

另一个例子涵盖了天然气含量较高的工作站不是解决方案:

/// <summary>
/// Station 1 - Gas: 3   Cost: 4
/// Station 2 - Gas: 10  Cost: 11
/// Station 3 - Gas: 8   Cost: 9
/// Station 4 - Gas: 6   Cost: 3
/// Station 5 - Gas: 4   Cost: 2
/// 
/// Then - Trip Balances are:
/// Station 1 - -1
/// Station 2 - -1
/// Station 3 - -1
/// Station 4 -  3
/// Station 5 -  2
/// </summary>
[TestMethod]    
public void SecondExample()
{
  var tripBalances = new List<int> { -1, -1, -1, 3, 2 };
  var resolver = new GasStationResolver();
  var indexOfGasStation = resolver.FindFirstStation(tripBalances);
  Assert.AreEqual(3, indexOfGasStation);
}

答案 6 :(得分:0)

找到气体最多的加油站,但加入油箱时下一站的气体何时不超过油箱的容量。

答案 7 :(得分:0)

这或许?

  • 找到气体含量最高的加油站
  • 列出所有加油站,并取其燃油值,减去那里的行驶费用
  • 驾驶至最高值的加油站
  • 重复访问所有加油站