题目大意:
Ber群岛由N个岛屿组成。将岛屿视作点,则组成它的岛屿围成了一个正N边形。
将岛屿按顺时针标号,岛屿N1的坐标是(x1,y1),岛屿N2的坐标是(x2,y2)
你的任务是 得到 N1,N2的坐标 求出所有N个点的坐标
输入:
在第一行,输入 N ,N1 和 N2 (3 ≤ N ≤ 150, 1 ≤ N1,N2 ≤ N, N1 ≠ N2) 由空格隔开。
接下来两行输入 N1 和 N2 的坐标(坐标的绝对值不会大于 2000000)
输出:
输出N行,表示N个点的坐标,按照点的标号顺序输出。结果保留6位小数。
样例输入:
4 1 3
1.0000 0.0000
1.0000 2.0000
样例输出:
1.000000 0.000000
0.000000 1.000000
1.000000 2.000000
2.000000 1.000000
又是计算几何...
题目就是由两个点还原一个正多边形
为了方便,假定a<b
下面介绍向量旋转方法:
思想很简单:找到正多边形的中心(内心)(外心和内心是同一个...)
引用一些性质:
性质一:正多边形任意两点的连线的中垂线经过该正多边形的中心。
证明:根据中垂线性质:中垂线上的点到两点的距离相等。
那么对于任意一个点i,i与其他点连线的中垂线交点到所有点的距离都相同。
与正多边形所有点距离相同的点就是中心。
性质二:对于向量(x,y)在逆时针旋转a度之后得到向量为(x*cosa-y*sina,x*sina+y*cosa)
证明的话可以自己在草稿纸上画一画,很容易证明。
有了以上性质,我们可以给出大致思路
1.根据两个点的连线找出中垂线,并且大致判断出中心的方向(即从两点的中点指向中心的向量方向)。
设中点为(xmid,ymid)
从中点向b点指一个向量。
若从a到b所经过的点>从b到a经过的点,则证明中心在a到b的方向上,将上面的向量逆时针旋转90°,否则将上面的向量顺时针旋转90°
2.根据两个点的序号关系得到两点与中心构成的中心角角度。
对于两个点a、b,中心角度为:a、b两点连线与中心的另一端的边数*(360°/n)。
3.根据中心角角度和1中的向量方向计算出中心的坐标。
设中心坐标为(xcenter,ycenter)
xcenter=xmid+lx*t;
ycenter=ymid+ly*t;
tan(cita/2)=DIS(mid,a)/DIS(center,mid)
将式子展开并合并,可以得到t与xcenter、ycenter。
4.从中心坐标引一条向量指向一个点。
5.通过旋转角度得到其他点的坐标。
听说有大神用相似做的,精度很高,但是很难想。
注意事项:1.计算机一般使用弧度制。
2.WA在TEST5的OIer,请仔细检查向量的旋转(也有可能是cita/2的问题)。
下面附上我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#define PI acos(-1)
struct p
{
double x,y;
}point[200],mid,center,l;
double numangle,length,cita,t,sum;
int n,a,b;
double SQR(double a)
{
return a*a;
}
double SQRDIS(struct p a,struct p b)
{
return SQR(a.x-b.x)+SQR(a.y-b.y);
}
struct p turn(struct p a,double angle)//(x,y)->(x*cosa-y*sina,x*sina+y*cosa)
{
struct p re;
re.x=a.x*cos(angle)-a.y*sin(angle);
re.y=a.x*sin(angle)+a.y*cos(angle);
return re;
}
struct p add(struct p a,struct p b)
{
struct p re;
re.x=b.x-a.x;
re.y=b.y-a.y;
return re;
}
void makepoint()
{
int i;
l=add(center,point[a]);
i=a;
do
{
point[i].x=center.x+l.x;
point[i].y=center.y+l.y;
l=turn(l,-numangle);
i++;
if (i>n)
i=1;
}while (i!=a);
return ;
}
void work()
{
if (b-a-1>a+n-b-1)
{
l=turn(l,PI/2);
cita=(a+n-b)*(numangle);
}
else
{
l=turn(l,-PI/2);
cita=(b-a)*(numangle);
}
cita/=2;
length=SQRDIS(mid,point[a]);
length/=SQR(tan(cita));
sum=SQR(l.x)+SQR(l.y);
t=sqrt(length/sum);
center.x=mid.x+l.x*t;
center.y=mid.y+l.y*t;
makepoint();
return ;
}
void init()
{
int i;
scanf("%d",&n);
scanf("%d%d",&a,&b);
scanf("%lf%lf",&point[a].x,&point[a].y);
scanf("%lf%lf",&point[b].x,&point[b].y);
if (a>b)
{ i=a; a=b; b=i; }
numangle=(2*PI/n);
mid.x=(point[a].x+point[b].x)/2;
mid.y=(point[a].y+point[b].y)/2;
l=add(mid,point[b]);
work();
for (i=1;i<=n;i++)
printf("%lf %lf\n",point[i].x,point[i].y);
return ;
}
int main()
{
init();
return 0;
}