如何解决涉及重叠对的问题以及使用哪种数据结构

时间:2012-02-27 06:11:48

标签: c algorithm optimization data-structures

我们有一个火车站的交通信息,它的相似(到达,离开)时间对列车来到车站。像这样的东西T {[1,5],[2,4],[5,9],[3,10]}。然后,如何找到管理此流量所需的最少平台数。

4 个答案:

答案 0 :(得分:2)

你需要找出最大重叠,对吧?这将为您提供最少数量的平台。只需初始化一个max(times)元素等于0的数组,然后添加迭代遍历每个(arrival, departure)间隔,为该区间中的数组的每个元素添加1。

然后,数组中任何元素的最大值是您需要的最小平台数。这适用于整数值区间。但是,该数组可能不是最快的方法。我会留给你的。

答案 1 :(得分:2)

在时间O(n log n)中存在一个解,其中n是给定的时间对的数量。 你必须回答这个问题:车站同时有多少列车? 为此,我们首先“标准化”时间值:确定所有时间段可能发生的有趣事件。为此,请对给定的所有到达和离开时间进行排序并消除重复。

在你的例子中,T = {[1,5],[2,4],[5,9],[3,10]},这会产生一个数组 A时间点[1,2,3,4,5,9,10],大小m = 7。

现在我们将每对的到达和离开时间转换为火车占用车站的时间段,即。即我们在数组A中找到时间值的索引(通过二进制搜索)。 E. g。对于[3,10],我们得到指数2和6,从零开始计算。

这就是容易的部分。使用索引对时间值进行排序和匹配,每个都以O(n log n)运行。现在我们必须计算每个指数,当时有多少列车站在车站。为了有效地做到这一点,我们使用了一个分段树。

该网站介绍了如何使用细分树: http://community.topcoder.com/tc?module=Static&d1=tutorials&d2=lowestCommonAncestor#Segment_Trees

在下文中,您将在C ++中找到一个实现。我希望你能适应你的需求。如果有任何问题仍未解决,请随时提出。

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

/** Given a number n and n pairs of arrival and departure times of trains,
*  this program calculates the number of platforms needed in time O(n log n)
*  If a train arrives exactly when another one leaves the station, you need
*  two platforms. */

int main () {
    int n;
    cin >> n;

    vector< pair<int,int> > T(n);
    vector< int           > A(2*n);

    for (int i = 0; i < n; ++i) {
        int arrival, departure;
        cin >> arrival >> departure;
        A[2*i]   = arrival;
        A[2*i+1] = departure;
        T[i] = pair<int,int>(arrival, departure);
    }
    sort(A.begin(), A.end());
    int m = unique(A.begin(), A.end()) - A.begin();

    // for easy indexing, we need m to be a potency of 2
    int pot2m = 1; while (pot2m < m) pot2m *= 2;

    // Elements pot2m ... pot2m + m represent the bottom layer of the segment tree
    vector< int > segtree(2*pot2m+1, 0);

    // Now let's add everything up
    for (int i = 0; i < n; ++i) {
        int arrival   = find(A.begin(), A.end(), T[i].first)  - A.begin();
        int departure = find(A.begin(), A.end(), T[i].second) - A.begin();
        // Now increment
        int a = arrival + pot2m;
        int b = departure + pot2m + 1;
        while (a < b) {
            if (a % 2 == 1) ++segtree[a];
            if (b % 2 == 1) ++segtree[b-1];
            a = (a+1) / 2;
            b = b / 2;
        }
    }

    // Find the maximum value in the cells
    int a = pot2m;
    int b = pot2m + m;
    while (a < b) {
        int i, j;
        for (i = a/2, j = a; j < b-1; ++i, j+=2) {
            segtree[i] += max(segtree[j], segtree[j+1]);
        }
        if (j == b-1) segtree[i] += segtree[j]; // To handle odd borders
        a /= 2;
        b /= 2;
    }
    cout << "You need " << segtree[1] << " platforms." << endl;

    return 0;
}

答案 2 :(得分:1)

我将继续讨论您的主题问题“如何解决这些问题以及哪种数据结构更适合处理?”

您已经举例说明了上述情况。这类问题称为优化问题(http://en.wikipedia.org/wiki/Optimization_problem)。

数据结构的选择将基于空间/时间权衡。因此,例如,可以通过使用简单数组或散列表或者图形来解决上述问题。真正重要的是有时可能需要指数运行时间来解决可能使它们成为NP-Complete / Hard的问题。假设您的例子中有n个平台和m个列车(其中n&amp; m非常大),那么就有可能发生组合爆炸。

此外,如果它导致指数时间并且说是NP完全/硬问题那么有几个启发式算法(例如,使用蚁群优化可以解决旅行推销员问题)也可以解决它,也许不是最优的一个。

在此上下文中算法比数据结构更重要。

答案 3 :(得分:1)

制作如下结构数组:(时间,IsArrival),其中IsArrival = +1抵达或-1离开

按时间键排序(考虑相同时间的情况)

初始化PlatformsNeeded = 0

遍历已排序的数组,将IsArrival添加到PlatformsNeeded,记住最大值