sgu120
来源:互联网 发布:苏州十大网络教育机构 编辑:程序博客网 时间:2024/04/30 13:11
题目大意:
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;}
- sgu120
- sgu120
- sgu120:Arhipelago
- SGU120 Archipelago
- [SGU120] Archipelago && 计算几何
- 复数加减
- 黑马程序员03
- 2014 ACM/ICPC 上海区域赛小记
- jsp内置对象值application对象
- util包下的map和collection接口下的link和set实现类
- sgu120
- N皇后问题
- 二叉树前序,中序,后续遍历(递归和非递归)
- oracle 11.2.0.4 rac 恢复到单实例
- libstdc++5的安装
- 5.判断一个链表是否存在环
- 赫夫曼编码
- Brownie Points II - POJ 2464 线段树
- 自定义Android标题栏TitleBar布局