公式我推不出,算法倒是有一个:
设矩形X轴Y轴上长度分别是M,N。
两直角边平行于坐标轴时,确定两个X坐标M(M+1)/2,确定两个Y坐标
N(N+1)/2,可以得到4个直角三角形。于是共有MN(M+1)(N+1)个。
两直角边与坐标轴不平行时,先找两个点(x1,y1)(x2,y2)确定一条斜率为正的直角边(二重循环),然后要求找(x3,y3),那么有|x2-x1|/|y2-y1|=(|y3-y1|/|x3-x1|或|y3-y2|/|x3-x2|),因为对于互补的角A和B有tgA=ctgB。
那么如何求第三个点呢?我想了一种方法,举例如下
设矩形左下为原点(0,0),右上为(100,200)。已知确定一条直角边两端点(6,7)和(10,13),现在要找第三个点,可能为(6-m,7+n)、(6+m,7-n)、(10-m,13+n)、(10+m,13-n)。那么就要找满足n/m=(10-6)/(13-7)=4/6的整数对(m,n)。先用辗转相除求出4和6的最大公因子,然后相约得到互质的整数对(2,3),则(m,n)必然是(3,2)、(6,4)、(9,3)...这样的形式。具体有多少个这样的第三个点,对于(10+m,13-n)来说,就是10+m<100,13-n>0,因此为(100-10)/3取整和(13-0)/2取整中较小的那个,其他三种形式同理。
复杂度计算:显然是(M*N*辗转相除法复杂度)
辗转相除法复杂度忘了,我大概推了一下,考虑边长m和n的矩形(m>n),相除一次后变成(n,p),显然有p<1/2(n+p)=1/2m,新矩形面积减少到原来一半以下,最坏情况一直相除直到2和1的情形,这时候的面积为2,所以相除次数不超过log(mn)=logm+logn。
显然算法中有m<=M,n<=N
因此算法复杂度为(M*N*(logM+logN)),满足楼主要求
修改:
我果然很粗心。。。
我刚刚又思考了一下,可以换个思路,先考虑斜边而不是两直角边,借用你的方法,首先不考虑平移,将斜边中心定为原点,由于原来中心点坐标可能为m/2,m为奇数的情况,因此将坐标均乘以2,确定了一条斜边后,要找到直角顶点(知道直角顶点的情况下确定斜边其实是一样的)。问题本质上就成为以该斜边直径的圆经过多少整点,本来要遍历的点是O(m+n)级别的(对所有不大于直径的x坐标,求y坐标是否整数),这样整个复杂度就变成了n^3,因此求整点的算法必须改进。
现在的问题就是对于(m,n),要求出所有满足m^2+n^2=a^2+b^2的(a,b),最后(n,m)(a,b)(b,a)都是可能满足条件的点(x,y),“可能”是因为还需要x-m和y-n都是偶数(因为坐标之前被乘以2)。所以事先可以对任意m和n,将(m,n)保存在S数组D的D[m^2+N^2]指向的地址中,这个地址指向的是一个保存了如上的(m,n)(n,m)(a,b)(b,a)...的链表(只统计个数是不行的,因为对于不同的(m,n),平移得到的三角形个数是不同的,必须保存(m,n),其实就是一个散列结构),这样对(m,n)求所有(a,b)可以直接查询,不过这样做空间开销很大,效率上不一定比之前求最大公约数高,虽然求公因子理论上为logN复杂度,实际运行平均效率远高于这个最坏值。
最后三角形大小形状角度确定后进行平移计算确实是O(1)复杂度,如楼下所说,因为三角形三顶点最大横坐标之差,最大纵坐标之差已经确定了,也就是说覆盖这个三角形的最小子矩形(边与坐标轴平行)已经确定了,把两个方向上平移的可能相乘就可以了。
感觉还是数学不过关,m^2+n^2=a^2+b^2应该有更好的计算方法的,就是想不出来。
温馨提示:答案为网友推荐,仅供参考