【问题标题】:Given list of horizontal lines in array, find the vertical lines that crosses the most lines给定数组中的水平线列表,找到穿过最多行的垂直线
【发布时间】:2022-06-11 23:33:27
【问题描述】:

问题

水平线如 (6 to 10), (9 to 11), (1, 20) 是点 a 到 b 并且代码应该找到一条穿过最大数量水平线的线。

所以,下面这几行,答案是 3,因为一条垂直线的最大数量是 3 行。

Example

6 10
10 14
1 5
8 11
13 15
10 12
12 16
2 7

对于如何有效解决这个问题有什么建议吗?

我尝试过的

  1. 我尝试过创建一个数组并通过迭代行的起点到终点来增加它的值。这样,可以检测到最大数量。运行时错误,代码很慢。
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
using namespace std;

int N, x, y, cnt, max_cnt = 0;
vector<pair<int, int>> end_points;

int main()
{
  cin >> N;

  for (int i = 0; i < N; i++) {
    cin >> x >> y;
    end_points.push_back(make_pair(x, 1));
    end_points.push_back(make_pair(y, -1));
  }

  sort(end_points.begin(), end_points.end());

  for (const auto &e : end_points)
  {
    cnt += e.second;
    max_cnt = max(max_cnt, cnt);
  }

  cout << max_cnt;
}

【问题讨论】:

  • 你所指的水平线是笛卡尔坐标吗?另外,你上面例子中的答案是 3 是什么意思?
  • 填充两个包含间隔的对向量,根据行首对另一个进行排序,根据行尾对另一个进行排序,然后并行行走,同时跟踪您在其中的间隔数和最大的。
  • 其实你只需要 int 的向量,一个保存起始位置,另一个保存结束位置
  • "运行时错误,代码很慢。"什么错误?
  • 您实际上并不是在寻找线路。您正在寻找一组集合之间的最大交点。

标签: c++


【解决方案1】:

考虑两个区间的例子

 0 1000000
 42 44

您不需要从 0 到 1000000 的循环来发现 43 在两个区间内。

您只需要考虑区间的端点。当它们被排序时,它们是0,42,44,1000000。然后循环这些端点。当终点是间隔的开始时,您增加计数,当它是间隔的结束时,您减少计数。那是 4 次迭代而不是 1000000 次。

以下假设在具有共同端点的区间之间没有重叠,例如,对于两个区间 (0,10) 和 (10,20),计数为 2 时没有点(即区间是开放的,对于闭合区间,只需进行少量修改)。

#include <sstream>
#include <vector>
#include <iostream>
#include <algorithm>
#include <utility>

int main()
{
    std::istringstream input {"6 10 \
                              10 14 \
                               1  5 \
                               8 11 \
                              13 15 \
                              10 12 \
                              12 16 \
                              2 7"};

    std::vector<std::pair<int,int>> end_points;
    int sta,sto;
    while (input >> sta >> sto) {
        end_points.push_back({sta,1});
        end_points.push_back({sto,-1});
    }

    std::sort(end_points.begin(),end_points.end());
    int count = 0;
    int max_count = 0;
    for (const auto& e : end_points) {
        count += e.second;
        max_count = std::max(max_count,count);
    }
    std::cout << max_count;
}

【讨论】:

  • 感谢您的回答。当然变得更快了,但是有什么方法可以进一步优化它吗?我正在解决一个问题,你的代码肯定比我的快,但我没有解决问题,因为最后 4 个运行得太慢了。
【解决方案2】:

在第一个 for 循环中递增网格值时可以更新最大值。

当增加数组值时,j &lt; y 应更新为 j &lt; (y + 1),因为您也必须增加 grid[y] 值。

您的示例的答案应该是 4。在点 10,一条垂直线将在 4 个点相交。

int N, x, y, maxv = 0, grid[1000001] = {0};

int main()
{
  cin >> N;

  for (int i = 0; i < N; i++)
  {
    cin >> x >> y;
    
    for (int j = x; j < (y + 1); j++)
    {
      grid[j]++;
      maxv = max(maxv, grid[j]);
    }
  }
  
  /*for (int i = 0; i < 1000001; i++)
    maxv = max(maxv, grid[i]);*/

  cout << maxv;
}

【讨论】:

  • 在示例案例中它甚至没有正确回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-30
  • 2013-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多