多个圆形成的相交区域数

时间:2018-10-31 19:37:11

标签: algorithm intersection

我们有四个参数可以画出一些圆圈:

  1. 圆的中心(x_1和x_2)都位于x轴上
  2. 最大半径(k_1和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

1 个答案:

答案 0 :(得分:3)

我提出了以下解决方案。

正如您所写,我们有两组圈子。一组的中心为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_1满足时,交换k_2k_1 < k_2

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

enter image description here enter image description here

特殊情况: enter image description here

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

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

enter image description here

这是我的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;
}