矩形网格中的右等腰三角形的数量

时间:2014-07-25 16:16:46

标签: algorithm math geometry

如何有效地计算nxm矩形网格中右等腰三角形的数量?

  • 三角形的3个角必须具有整数坐标。
  • 三角形的右侧不一定与网格线平行。

3 个答案:

答案 0 :(得分:3)

设A是直角所在的三角形角。设ab是第一个角的差矢量,而是另一个角的差矢量。 ac应始终留在ab。因此,对于给定的ab,我们可以将ac计算为:

ac = (-ab.y, ab.x)

因此,给定A,某个三角形只有两个整数自由度。我们可以计算ab的可能间隔:

A.x + ab.x >= 0   -->  ab.x >= -A.x
A.x + ab.x <= m   -->  ab.x <= m - A.x
A.y + ab.x >= 0   -->  ab.x >= -A.y
A.y + ab.x <= n   -->  ab.x <= n - A.y

A.y + ab.y >= 0   -->  ab.y >= -A.y
A.y + ab.y <= n   -->  ab.y <= n - A.y
A.x - ab.y >= 0   -->  ab.y <= A.x
A.x - ab.y <= m   -->  ab.y >= A.x - m

所以可能的间隔是

xmin = max(-A.x, -A.y)
xmax = min(m - A.x, n - A.y)
ymin = max(-A.y, A.x - m)
ymax = min(n - A.y, A.x)

满足这些条件的可能向量的数量(0向量除外)是:

c = (xmax - xmin + 1) * (ymax - ymin + 1) - 1

所需结果是网格中所有可能A的c之和。使用朴素的方法,您将获得O(grid cells)运行时。根据你的网格,这已经足够快了。

更新

为了分割c的总和(在所有网格单元格上),我们必须确定maxmin操作的结果在何处发生变化。例如。 ymax更改如下:

Grid 1

请注意,我已经将线偏移了一点,因此从点到点所属的区域有一个独特的映射。

当我们对所有区间边界执行此操作时,我们得到以下图片(对于m> n):

Grid 2

现在我们可以独立计算每个区域c的总和。我将示例性地显示最左边的三角形区域。

对于该地区,以下条件成立:

xmin = -A.y
xmax = n - A.y
ymin = -A.y
ymax = A.x

c(x, y) = (n - y + x) * (x + y) - 1
        = (nx + ny - y^2 + x^2 - 1)

现在我们对该地区的所有xy进行总结。 x从0到n/2yxn-x

所以我们得到:

                n/2  n-x
sumLeftRegion = Sum  Sum  (nx + ny - y² + x² - 1) 
                x=0  y=x

我们可以解决这个问题(例如,使用您最喜欢的代数程序并获取:

sumLeftRegion = 1/48 * (2 + n)*(-24 - 14n + 6n^2 + 5n^3)

可以对所有其他地区进行此操作。您需要一些案例(例如m > nm = nm < n,可能是偶数nm)。通过旋转网格(不会更改可能的三角形的数量),可以将案例n > m转换为m > n。这将是一些工作,但最终你会得到O(1)的结果,因为没有迭代。

答案 1 :(得分:0)

考虑RAIT ABC。如果我们在(0,0)处保持三角形的拐角(A),那么我们可以说对于y = 1(so(1,1),(2,1)等的每个正点(B)存在一个RAIT,其另一个角(C)位于(n,n),其中Cn = Bx-1。显然,对于y = 2也必须为真(从B(2,2)开始,y = 3 (从B(3,3)等开始 - 你只是加倍,三倍,等等。这有帮助吗?(我不是数学家 - 如果不明显的话)

答案 2 :(得分:0)

考虑方框中的任何三角形。它有一个独特的边界框(在某种意义上它只有一个,而不是它是唯一带有该边界框的三角形)。因此,如果您考虑每个可能的边界框边长(i,j),并使用此边界框计算RAIT三角形的数量(表示此CP(i,j)),那么您的答案为sum(i=1 to n, sum(j=1 to m,CP(i,j)*(m-j+1))*(n-i+1))(m-j+1)*(n-i+1)正在计算n*m框中可容纳的大小框的数量。所以现在很难找到CP(i,j)。同样,CP(i,j)是RAIT三角形的数量,在框的周长上有点,长度为ij。我们可以在这里使用对称性。假设不失一般性,直角是ABC。想象一下,三角形与正轴对齐。

A 
|\
| \
B__C

现在考虑顺时针旋转它直到它自身回线。通过该过程有两种可能性:BC位于象限1和2或象限3和4中。

2|1
---
3|4

我们在这里注意到,在第一种情况下,B位于边界框的底部或右侧,而在第二种情况下,B位于边界框的顶部或左侧。所以wlog我们假设B位于底部或右侧,不包括左下角。

+-----*
|     *
|     *
+******

一旦我们计算出有多少个RAIT三角形有这个属性,我们就可以加倍它! 如果B位于右上角,则只有一个三角形可以测试RAIT-ness,如果它位于右下角则相同。如果它沿着右侧墙壁,那么有一些三角形要检查(在顶部的每个点放置C,并计算第三个点以查看它是否形成给定的边界框)。同样,如果它沿着底壁,那么有j个三角形要检查。

这肯定比O(m * n)差,它可能在O(m ^ 2 * n ^ 2)附近,但希望这会有所帮助。

修改

我们在测试三角形中实际上可以做得更好一点。通过一点几何直觉,我们可以看到,如果B沿着底部,并且更靠近右下角,则C位于右上角。同样,如果它更接近左下角,则A位于右上角。所以我们可以考虑B的一半位置,对于每个位置我们只需要考虑一个可能的三角形。 (B在右边的论点是相似的。)