递归创建apollonian垫片

Apollonian垫圈=它们是由圆的三元组产生的平面分形,其中每个圆与另外两个圆相切。 在他的垫圈图中,我们从两个外切圆开始,直径为D1和D2。 然后我们添加第三个圆,其直径为D1 + D2,两个原始圆在内部相切。 这是第一代圈子。 通过应用以下方案构造每个后续一代圆:对于任何前一代的彼此相切的任何三个圆A,BC,构造与A,B,C相切的新圆。 新圈子必须与目前构建的所有圈子不同。 当一代人完成时,即不能添加其他圈子,则可以开始构建下一代圈子。

还有一个额外的停止规则可防止产生无限小的圆圈。 当且仅当其直径的长度为最小minD(其为固定的正值)时,可以将圆圈添加到垫圈中。

输入由一行包含三个十进制数D1,D2和minD组成。 数字用空格分隔。 格式为通常的十进制格式(参见下面的示例),没有指数部分。 它认为1.0≤D1,D2≤1000.0,0.001≤minD≤D1+ D2。

输出由一个包含两个十进制数L1和L2的文本行组成。 L1表示垫圈中除圆圈之外的所有圆的面积之和。 L2表示垫圈中锡的所有圆的周长之和,除了最大圆圈。 两个输出值都舍入为6位十进制数字。 输出中必须始终存在十进制数字,即使其中一些数字为零。 Maximim输出值小于107。

输入

17.000000 40.000000 1.000000 

产量

 2439.258588 835.263228 

在此处输入图像描述

在此处输入图像描述 2

对于给定的D1和D2,我像这样创建这两个圆圈(第一次迭代):

  double D1 = 17.00; double D2 = 40.00; double minD = 1.00; int i = 250, j = 350; comp.addCircle(i, j, (int) D2, randomColor); comp.addCircle(i + (int) D2 / 2 + (int) D1 / 2, j, (int) D1, randomColor); comp.addCircle(i + (int) D1 / 2, j, (int) (D1 + D2), randomColor); 

更新:

因此,解决方案基于笛卡尔定理 。 我们很好地使用半径 ,而不是直径, 曲率 ,是1/r 。 我们将使用double进行所有计算,但如果你使用非常小的数字,我更喜欢BigDecimal。 它会减慢算法,你应该使用外部方法来查找平方根,因为BigDecimal没有任何。

对于给定的D1,D2,minD,我们修改上面的代码以提高效率:

一些准备:

  double D1 = sc.nextDouble() / 2; double D2 = sc.nextDouble() / 2; minD = sc.nextDouble() / 2; double D3 = D1 + D2; 

所以,第一步看起来像这样: 在此处输入图像描述

下一步看起来有点复杂。

假设我们想要写一个递归来解决这个问题,并根据笛卡尔定理,给出三个圆的给定曲率,彼此相切,(下图) 在此处输入图像描述在此处输入图像描述 ,我们可以找到两个圆的曲率, 但是对于我们的目的,我们只需要一个小圆,所以,我们可以简化公式

 this.curve = a.curve + b.curve + c.curve + 2 * Math.sqrt(Math.abs(a.curve * b.curve + a.curve * c.curve + b.curve * c.curve)); 

让我们再看看Apollonian垫圈: 试着玩它 。 看到? 它是相同的垫圈,但具有不同的启动条件。 对我们来说更重要的是,它是对称的! 所以,我们只计算一半,然后将结果乘以2! 让我们写一个递归! 输入将是三个圆的曲率。 没有输出,我们将使用更改我们的全局变量。

 double radius_sum = 0.0; double square_radius_sum = 0.0; void createAG(double a, double b, double c){ double n = a + b + c + Math.sqrt(a*b + a*c + b*c + 4.0); if ((minD * n) < 1){ radius_sum += 2. / n; //Remember about symmetry? square_radius_sum += 2. * (1. / n) * (1. / n); //Remember about symmetry? createAG(a, b, n); createAG(a, c, n); createAG(b, c, n); } } 

为了找到结果,我们将使用公式来计算圆的面积和周长。 周长是周长,等于 在此处输入图像描述 。 面积等于 在此处输入图像描述 ,正如您已经知道的那样,因为我们已经在上一步计算了它,否则我们必须存储每个半径并进行更多计算。

 radius_sum = 2 * Math.Pi * radius_sum; square_radius_sum = Math.Pi * square_radius_sum; 

但是我们忘记了前两个圈子! 我们来解决它吧!

  radius_sum += D1*2 + D2*2; square_radius_sum += D1*D1 + D2*D2; radius_sum = 2 * Math.Pi * radius_sum; square_radius_sum = Math.Pi * square_radius_sum; 

而且总有改进的余地。 例如,为了更好地使用IEEE 754 ,我假设您将使用1. / x而不是1 / x

谢谢!

PS版权! 这项任务(Apollonian垫片的文字和第一张图片)由CTU的教师创建,当然是ALG 。 公式的图片来自维基百科。 其他一切都是公共领域,如果没有专利,注册等

因此,解决方案基于笛卡尔定理 。 我们很好地使用半径 ,而不是直径, 曲率 ,是1/r 。 我们将使用double进行所有计算,但如果你使用非常小的数字,我更喜欢BigDecimal。 它会减慢算法,你应该使用外部方法来查找平方根,因为BigDecimal没有任何。

对于给定的D1,D2,minD,我们修改上面的代码以提高效率:

一些准备:

  double D1 = sc.nextDouble() / 2; double D2 = sc.nextDouble() / 2; minD = sc.nextDouble() / 2; double D3 = D1 + D2; 

所以,第一步看起来像这样: 在此处输入图像描述

下一步看起来有点复杂。

假设我们想要写一个递归来解决这个问题,并根据笛卡尔定理,给出三个圆的给定曲率,彼此相切,(下图) 在此处输入图像描述在此处输入图像描述 ,我们可以找到两个圆的曲率, 但是对于我们的目的,我们只需要一个小圆,所以,我们可以简化公式

 this.curve = a.curve + b.curve + c.curve + 2 * Math.sqrt(Math.abs(a.curve * b.curve + a.curve * c.curve + b.curve * c.curve)); 

让我们再看看Apollonian垫圈: 试着玩它 。 看到? 它是相同的垫圈,但具有不同的启动条件。 对我们来说更重要的是,它是对称的! 所以,我们只计算一半,然后将结果乘以2! 让我们写一个递归! 输入将是三个圆的曲率。 没有输出,我们将使用更改我们的全局变量。

 double radius_sum = 0.0; double square_radius_sum = 0.0; void createAG(double a, double b, double c){ double n = a + b + c + Math.sqrt(a*b + a*c + b*c + 4.0); if ((minD * n) < 1){ radius_sum += 2. / n; //Remember about symmetry? square_radius_sum += 2. * (1. / n) * (1. / n); //Remember about symmetry? createAG(a, b, n); createAG(a, c, n); createAG(b, c, n); } } 

为了找到结果,我们将使用公式来计算圆的面积和周长。 周长是周长,等于 在此处输入图像描述 。 面积等于 在此处输入图像描述 ,正如您已经知道的那样,因为我们已经在上一步计算了它,否则我们必须存储每个半径并进行更多计算。

 radius_sum = 2 * Math.Pi * radius_sum; square_radius_sum = Math.Pi * square_radius_sum; 

但是我们忘记了前两个圈子! 我们来解决它吧!

  radius_sum += D1*2 + D2*2; square_radius_sum += D1*D1 + D2*D2; radius_sum = 2 * Math.Pi * radius_sum; square_radius_sum = Math.Pi * square_radius_sum; 

而且总有改进的余地。 例如,为了更好地使用IEEE 754 ,我假设您将使用1. / x而不是1 / x

谢谢!

PS版权! 这项任务(Apollonian垫片的文字和第一张图片)由CTU的教师创建,当然是ALG 。 公式的图片来自维基百科。 其他一切都是公共领域,如果没有专利,注册等