1

我正在为学校做一个项目,并试图决定我应该如何去做。

这是一个餐厅模拟。我生成一张桌子和等候方的随机列表。我随机安排了一些派对,有些派对没有在等候名单上。我希望有保留的各方拥有第一优先权。

是否对列表进行排序,以便所有有保留的各方都在一端,而没有另一端的一方是解决这个问题的好方法?

然后我可以评估列表,看看派对是否适合在桌子上,然后让他们入座或继续下一个派对。还是有更聪明的方法来解决这个问题?任何输入表示赞赏!

4

5 回答 5

6
var groupedParties = parties.GroupBy(p => p.HasReservation);

这是迄今为止我看到的最干净的方式。你会得到一个包含两个组的列表,一个包含没有的缔约方,一个包含有保留的缔约方。您现在可以分别处理不同类型的等候派对的座位。

编辑

static void Main(string[] args)
{
    GenerateRandomDataSomehow();
    var groupedParties = _parties.GroupBy(p => p.HasReservation)
    SeatParty(groupedParties.FirstOrDefault(g => g.Key == true));
    SeatParty(groupedParties.FirstOrDefault(g => g.Key == false));
}

private static void SeatParty(IEnumerable<Party> partyGroup)
{
    if (partyGroup == null) return;

    foreach (var party in partyGroup.OrderBy(p => p.ArrivalTime))
    {
        var properTable = _tables.FirstOrDefault(t => t.SeatsCount == party.PersonsCount &&
                                                      t.Party == null);
        if (properTable == null) continue;
        properTable.Party = party;
    }
}

这是一个带有更多 LINQ 的非常简单的实现。选择标准需要适当扩展。在此表中,如果没有其他方坐在此表上,则将其评估为“适当”,但如果人数准确,则相应表的座位数。如果找不到合适的表,则跳过该组。

于 2013-03-01T10:29:10.850 回答
3

您可能希望使用Queue或类似队列的构造而不是 List 来为您的餐厅建模,并采用不同的方法。这样,您将按照人员到达的顺序存储人员,因此无需进行排序。

将人员分组到一个 Party 对象中。当派对到达时,您可以将它们添加到队列中。然后,您可以查看队列,如果一方有预订,您可以将其从队列中删除并将其发送到他们的餐桌。如果该聚会没有预订,那么您检查是否有桌子可供该大小的聚会使用,如果有,则将该聚会从队列中移除。

否则,您可以等到 Table 可用;当该事件发生时,您可以再次排队,寻找适合餐桌大小的派对。您还可以在此时检查队列中是否包含有预订的派对,这意味着他们优先 - 用于Queue.First(x => x.HasReservation && x.Size <= Table.Places)从队列中获取第一组有预订并且可以坐在桌子上的人**。否则,Queue.First(x => x.Size <= Table.Places)将让您排在队列中的第一批适合坐在桌子旁的人。

使用队列的优点是不需要排序,您可以按照到达的顺序处理多人,优先考虑有预订的人。

您在两点检查队列:

  1. 当人们到达时(他们是否有预订,是否有空位)
  2. 当有空位时 - 首先在队列中寻找已预订并能够坐到餐桌上的人;如果没有匹配,则从队列中取出与桌子大小匹配(或可以放在桌子上)的第一组人

这是一个很好的起点。

更新

正如您所发现的,您无法从队列中间移除项目。这是因为队列是先进先出 (FIFO) [与堆栈相反,堆栈是后进先出 - LIFO]。为了避免排序,您可以使用具有类似语义的队列的列表 -这个答案中有一个很好的例子。

** 这里还有另一个有趣的排队问题——效率问题。如果有 4 个位置的桌子可用,你会怎么做?把它给第一个到达的适合在桌子上的一方,或者给它在队列中适合在桌子上的最大的一方。显然,第一个选项最适合客户服务,因为您坐着等待时间最长的人,但第二个选项可以最大化您的利润,因为您可以更充分地利用桌子:-)

于 2013-03-01T10:45:50.377 回答
2

如果要对列表进行排序:

使用Enumerable.OrderByDescending,ThenByDescending

var ordered = parties.OrderByDescending(p => p.HasReservation)
                     .ThenByDescending(p => p.PersonCount);
// if you want a new list use ordered.ToList()
foreach(var party in ordered)
{
    // ...
}

如果要对原始列表进行排序,可以使用List<T>.Sort自定义委托:

parties.Sort((p1, p2) =>
{
    if (p1.HasReservation != p2.HasReservation)
        return p1.HasReservation ? 1 : -1;
    else
        return p1.PersonCount.CompareTo(p2.PersonCount);
});
于 2013-03-01T10:30:30.373 回答
0

我会简单地使用两个队列(假设您的各方由一个名为Party. 的类型表示。适当地更改类型):

Queue<Party> withReservation = new Queue<Party>();
Queue<Party> withoutReservation = new Queue<Party>();

您可以像这样将派对添加到队列中:

if (party has reservation) { // (condition in pseudo code)
    withReservation.Enqueue(party);
} else {
    withoutReservation.Enqueue(party);
}

你会坐在这样的派对上:

if (withReservation.Count > 0) {
    Seat(withReservation.Dequeue());
} else if (withoutReservation.Count > 0) {
    Seat(withoutReservation.Dequeue());
}
于 2013-03-03T15:38:01.240 回答
0

在这种情况下,使用System.Linq可能是您对列表进行排序的最佳选择。

就像是:

var sorted = tables.OrderByDescending(o => o.IsReserved);
于 2013-03-01T10:30:34.430 回答