【问题标题】:Number of intersection regions made by multiple circles多个圆形成的相交区域数
【发布时间】:2018-10-31 19:37:10
【问题描述】:

我们有四个参数来绘制一些圆圈:

  1. 圆心(x_1 和 x_2),都位于 x 轴上
  2. 最大半径(k_1 and k_2) 这就是我们使用这个信息的方式:第一组圆中心位于x_1,我们从这里绘制k_1个不同半径的圆,从1到k_1:(1<= r_1 <= k_1)所以第一个圆的半径为1并居中在 x_1 ,第二个的半径为 2 ...第二组圆也适用相同的条件。最后,有些圆可能会或可能不会相互交叉。我想要的是总数最后制作的区域。我认为,如果我了解将两个区域分开的原因,则主要解决了问题。为了清楚起见,这里有一些示例(请注意,所有参数都在:[1,10^5] 范围内):

    for:x_1 = 1,k_1 = 1,x_2 = 0,k_2 = 1 => n = 3
    for: x_1 = 0,k_1 = 1,x_2 = 2,k_2 = 1 => n = 2
    for:x_1 = 3,k_1 = 3,x_2 = 7,k_2 = 4 => n =16

【问题讨论】:

  • 那么x_1x_2就是我们通常所说的(x,y)坐标?
  • @JimMischel 我认为从例子中(x,y)的中心坐标是(x1, 0)(x2, 0)
  • @btilly 重新阅读问题后,我认为您是对的。
  • 你为什么不试着用这些例子给自己画几张照片呢?这会让你看到交叉区域。
  • @JimMischel 当然我试过了(这就是我在示例中找到区域数量的方法)但我需要一种算法,它可以仅使用我在问题中引入的变量给出最终结果跨度>

标签: algorithm intersection


【解决方案1】:

我想出了以下解决方案。

正如您所写,我们有两组圆圈。一个集合的中心是x_1,另一个集合的中心是x_2 我们将集合分别表示为LR,其中

L = 以x_1 为中心的圆的集合和 R = 圆心为x_2x_1 <= x_2 的圆集。

现在算法步骤:

  1. 首先检查LRx_1x_2)的中心是否相等。如果相等,则这两个集合是同心的。所以答案是k_1k_2的最大值。

  2. 我们必须确保x_1 <= x_2。如果x_1 > x_2,则交换(x_1x_2)。

  3. 首先在这个算法中,我们将计算集合L 的每个圆圈中的区域数。然后我们将计算集合R 中那些在x_1 + k_1 之外的区域计数。因此,为了保持良好状态,我们需要 交换k_1k_2,当且仅当k_1 < k_2 相遇。

  4. 现在x_1 <= x_2 为真,我们将计算集合L 中每个圆圈内的所有区域。然后遍历从x_1 + 1x_1 + k_1的所有位置,并执行以下操作,并尝试从图中捕捉不同情况下区域计数的计算:

特殊情况:

  1. 我们仍然需要检查另一件事。将R 集合中的区域计数添加到x_1 + k_1 之外。

    • 如果 x_1 + k_1 dif = (x_2 + k_2) - (x_1 + k_1) 和 result = result + min(k_2, dif)

这是我的c++ 实现:

#include <iostream>
using namespace std;

int intersection_count(int x_1, int k_1, int x_2, int k_2) {
    if (x_1 == x_2)
        return max(k_1, k_2);

    if (x_1 > x_2) {
        swap(x_1, x_2);
    }
    if (k_1 < k_2) {
        swap(k_1, k_2);
    }

    int result = 0;
    for (int i = 1; i <= k_1; i++) {
        int pos = x_1 + i;
        int rev_pos = x_1 - i;
        if (pos <= x_2 - k_2) {
            result++;
        }
        else if (pos <= x_2) {
            int dif = pos - (x_2 - k_2);

            // check if the ith circle is cmpletely inside range [x_2 - k_2, x_2 + k_2]
            dif -= (rev_pos < x_2 - k_2) ? 0 : (rev_pos - (x_2 - k_2) + 1);

            result += 2*dif;
        }
        else if (pos <= x_2 + k_2) {
            int dif = (x_2 + k_2) - pos + 1;

            // check if the ith circle is cmpletely inside range [x_2 - k_2, x_2 + k_2]
            dif -= (rev_pos < x_2 - k_2) ? 0 : (rev_pos - (x_2 - k_2) + 1);

            result += 2*dif;
        }
        else {
            result++;
        }
    }
    if (x_1 + k_1 <= x_2 + k_2) {
        int dif = (x_2 + k_2) - (x_1 + k_1);
        result += min(k_2, dif);
    }

    return result;
}

int main(int argc, char const *argv[])
{
    cout << intersection_count(1, 1, 0, 1) << endl;
    cout << intersection_count(0, 1, 2, 1) << endl;
    cout << intersection_count(3, 3, 7, 4) << endl;
    cout << intersection_count(0, 1, 0, 2) << endl;
    cout << intersection_count(2, 1, 3, 2) << endl;
    cout << intersection_count(2, 1, 3, 3) << endl;
    cout << intersection_count(3, 4, 5, 3) << endl;
    cout << intersection_count(0, 7, 2, 7) << endl;

    return 0;
}

【讨论】:

  • tnx 的答案,但有一个错误,例如:0 1 0 2 基本上它是另一个圆圈内的一个圆圈,结果应该是 2 但这个算法返回 5
  • @FarzinNasiri 感谢您指出这种情况。我只是在编写解决方案时忘记处理这种情况。它在我的脑海里。但不知怎的,我忘记了。
  • @FarzinNasiri 是的。你是绝对正确的。是我的错。我刚刚检查了一般情况。我应该更加小心地处理它。我想我有一个解决方案。让我试试这个。
  • @FarzinNasiri 我已经编辑了解决方案。我认为现在还可以。感谢您再次纠正我。
  • 很抱歉我给你带来了这么多问题!但我想我发现了另一个错误3 4 5 3。如果你计算它们,结果将是 19,但算法返回 21。问题是第一次执行 for 循环。它计算了 2 个额外的区域。
猜你喜欢
  • 2013-07-02
  • 1970-01-01
  • 1970-01-01
  • 2015-08-30
  • 1970-01-01
  • 2015-05-31
  • 1970-01-01
  • 1970-01-01
  • 2018-05-24
相关资源
最近更新 更多