问题描述
请编写一个程序,输入整数n,输出科赫曲线的顶点坐标,该科赫曲线由深度为n的递归调用画出。
科赫曲线是一种广为人知的不规则碎片形。不规则碎片形是具有递归结构的图形,可以通过下述递归函数的调用画出。
1.将给定线段(p1, p2)三等分。
2.以三等分点s, t为顶点作出正三角形(s, u, t)。
3.对线段(p1, s), 线段(s, u), 线段(u,t), 线段(t, p2)递归地重复进行上述操作,设端点为(0, 0), (100, 0)。
输入: 输入1个整数n。
输出: 输出科赫曲线各顶点的坐标(x, y),每个点的坐标占一行。输出时请从端点(0,0)开始,沿连续线段顺次输出顶点坐标,到端点(100, 0)结束。输出误差不得超过0.0001。
限制: 0≤n≤6
输入示例
1
输出示例
0.00000000 0.00000000
33.33333333 33.33333333
50.00000000 28.86751346
66.66666667 0.00000000
100.00000000 0.00000000
讲解
koch函数包含3个参数,分别是递归深度d,以及线段的两个端点p1,p2。这个递归函数首先会求出线段p1, p2的三等分点s, t, 然后求能够使得线段su, ut, ts组成正三角形的点u。接下来,函数会顺次进行以下处理,从而描绘成线段。
1.对线段p1s递归调用koch,输出s的坐标。
2.对线段su递归调用koch,输出u的坐标。
3.对线段ut递归调用koch,输出t的坐标。
4.对线段tp2递归调用koch。
u的坐标可通过矢量运算求得。首先,s与t的坐标可通过以下算式求出。
s.x = (2 * p1.x + 1 * p2.x)/3
s.y = (2 * p1.y + 1 * p2.y)/3
t.x = (1 * p1.x + 2 * p2.x)/3
t.y = (1 * p1.y + 2 * p2.y)/3
以点s为起点,将点t逆时针旋转60°,即可得到点u。我们在这里采用旋转矩阵(一种以原点为中心进行旋转变换时常用的矩阵),通过下面的式子求出点u。
u.x = (t.x - s.x) * cos60° - (t.y - s.y) * sin60° + s.x
u.y = (t.x - s.x) * sin60° + (t.y - s.y) * cos60° + s.y
只要对初始状态的端点p1,p2调用koch,我们就可以按顺序输出从p1到p2的所有顶点。
AC代码如下
#include<stdio.h>
#include<math.h>
#define M_PI 3.14159265358979323846
struct Point{double x, y; };
void koch(int n, Point a, Point b){
if(n == 0) return;
Point s, t, u;
double th = M_PI * 60.0/180.0;//将单位从度变为弧度
s.x = (2.0 * a.x + 1.0 * b.x) / 3.0;
s.y = (2.0 * a.y + 1.0 * b.y) / 3.0;
t.x = (1.0 * a.x + 2.0 * b.x) / 3.0;
t.y = (1.0 * a.y + 2.0 * b.y) / 3.0;
u.x = (t.x - s.x) * cos(th) - (t.y - s.y) * sin(th) + s.x;
u.y = (t.x - s.x) * sin(th) - (t.y - s.y) * cos(th) + s.y;
koch(n - 1, a, s);
printf("%.8f %.8f\n", s.x, s.y);
koch(n - 1, s, u);
printf("%.8f %.8f\n", u.x, u.y);
koch(n - 1, u, t);
printf("%.8f %.8f\n", t.x, t.y);
koch(n - 1, t, b);
}
int main(){
Point a, b;
int n;
scanf("%d", &n);
a.x = 0;
a.y = 0;
b.x = 100;
b.y = 0;
printf("%.8f %.8f\n", a.x, a.y);
koch(n, a, b);
printf("%.8f %.8f\n", b.x, b.y);
return 0;
}