我在接受采访时得到了这个问题而我无法解决。
你有一条环形公路,有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();
}
}
由于
答案 0 :(得分:5)
解决这个问题的一个简单方法是使用强力方法。即尝试每一个可能性并抛弃那些不起作用的东西。
即。依次从每个加油站开始(下面重复每个起始站)。
(gas >= gasToMoveToNextStationNeeded)
编辑按照@ Vash的回答,作为决定从哪里开始的改进,打折自己没有足够气体的车站到达下一站并按顺序开始工作气体量(下降)。
请注意,这假设我们访问所有加油站。如果您需要最佳解决方案,则需要改进跳过加油站(问题没有说明这一点)。
答案 1 :(得分:2)
这是@George Duckett回答的优化案例。
如果你到达了起始站 - 问题就解决了。
如果在某个电台上你没有足够的燃料来接下一个
如果你逆时针走到已经访问过的车站 - 运气不好,车站上没有足够的燃料可以完全循环。
答案 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)
这或许?