计算几何-UESTC 484 Division
2015-05-27 12:54
260 查看
题意:给一个萌点,找到经过这个萌点的射线可以平分多边形。
题解:
1、遍历角度会wa,需要遍历距离。因为枚举角度的话会用到三角函数,听说会损失精度。
2、二分的时候二分五六十次不然100次就差不多了,我把精度弄成了l和r相差10的-7次方就wa了。真2。
3、如何判断两个端点是不是在边上呢?!我一开始枚举斜率,这么损失精度的方法真是蠢死了。叉积:a X b = |a||b|sinα 。也就是说a和b的角度小于180的话,叉积大于0,大于180的话,叉积小于0。最右的端点和萌点的连线和其余点和萌点的连线叉乘一定全都大于0或者共线,最左端点和萌点的连线和萌点的连线叉乘一定全部大于0或者共线。
4、注意多边形的顶点。判断是否在线段上的时候算左边点不算右边点就好了。而且还要判一下交点是不是多边形顶点。
5、总结一下。先通过叉乘不小于0找到最右端点,再通过叉乘不大于0找到最左端点,做一条线段,遍历距离。然后得到一条直线和一个多边形。
6、5之后的方法1:通过叉乘找到所有在这条线右边的顶点,加入新多边形的点集,(算上共线),找到和线段的交点加入点集(不算上端点)。
7、5之后的方法2:记录端点号,把两个交点加入点集,以及从较小端点到较大端点的所有端点序号。(注意判一下是不是交点,如果已经加进去过了就别加了)。然后看看最右端点在不在集合中。以此来判断算出的多边形面积是啥
8、6或者7之后,得到新多边形面积,如果刚好是“多边形/2”就找到了。
题解:
1、遍历角度会wa,需要遍历距离。因为枚举角度的话会用到三角函数,听说会损失精度。
2、二分的时候二分五六十次不然100次就差不多了,我把精度弄成了l和r相差10的-7次方就wa了。真2。
3、如何判断两个端点是不是在边上呢?!我一开始枚举斜率,这么损失精度的方法真是蠢死了。叉积:a X b = |a||b|sinα 。也就是说a和b的角度小于180的话,叉积大于0,大于180的话,叉积小于0。最右的端点和萌点的连线和其余点和萌点的连线叉乘一定全都大于0或者共线,最左端点和萌点的连线和萌点的连线叉乘一定全部大于0或者共线。
4、注意多边形的顶点。判断是否在线段上的时候算左边点不算右边点就好了。而且还要判一下交点是不是多边形顶点。
5、总结一下。先通过叉乘不小于0找到最右端点,再通过叉乘不大于0找到最左端点,做一条线段,遍历距离。然后得到一条直线和一个多边形。
6、5之后的方法1:通过叉乘找到所有在这条线右边的顶点,加入新多边形的点集,(算上共线),找到和线段的交点加入点集(不算上端点)。
7、5之后的方法2:记录端点号,把两个交点加入点集,以及从较小端点到较大端点的所有端点序号。(注意判一下是不是交点,如果已经加进去过了就别加了)。然后看看最右端点在不在集合中。以此来判断算出的多边形面积是啥
8、6或者7之后,得到新多边形面积,如果刚好是“多边形/2”就找到了。
#include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define SIZE_N 330 #define INF 0x3f3f3f3f using namespace std; const double PI = acos(-1); const double eps = 1e-8; const double eps1 = 1e-5; int cmp(double x) { if (fabs(x)< eps) return 0; if (x>0) return 1; return -1; } struct point { double x,y; point(){} point (double a, double b): x(a),y(b) {} friend point operator + (const point &a, const point &b){ return point(a.x + b.x, a.y + b.y); } friend point operator - (const point &a,const point &b){ return point(a.x - b.x, a.y - b.y); } friend point operator * (const double &a, const point &b){ return point(a * b.x, a * b.y); } friend point operator * (const point &a, const double &b){ return point(a.x * b, a.y * b); } friend point operator / (const point &a, const double &b){ return point(a.x/b, a.y/b); } friend bool operator == (const point &a, const point &b){ return cmp(a.x-b.x) == 0 && cmp(a.y-b.y) == 0; } }p[SIZE_N],ptemp[SIZE_N]; struct line { point a,b; }line1[SIZE_N]; double l,r;//从0到1二分距离 int N; int left,right;//最左边点的序号和最右边点的序号 double ar; double det(const point &a,const point &b) { return a.x * b.y -a.y * b.x; } double dot(const point &a,const point &b) { return a.x * b.x + a.y *b.y; } bool PointOnSegment (point p,point s,point t) {//p在st上面! return cmp(det(p-s,t-s))== 0 && cmp(dot(p-s,p-t))<= 0; } bool parallel(line a, line b) { return !cmp(det(a.a - a.b, b.a - b.b)); } bool line_make_point(line a,line b, point &res) { if (parallel(a,b)) return 0; double s1 = det(a.a-b.a, b.b - b.a); double s2 = det(a.b - b.a, b.b - b.a); res = (s1 * a.b - s2 * a.a)/(s1-s2); if(b.b == res ) return 0; if (PointOnSegment(res,b.a,b.b)) return 1; return 0; } int cmin,cmax; point res1,res2; double area(point a[],int n) { double sum = 0; a = a[0]; for (int i = 0; i < n; i++){ sum+= det(a[i],a[i+1]); } sum = fabs(sum); return sum/2.0; } double getarea(int cmin,int cmax) { int num = 0; ptemp[num++] = res1; int isright = 0; for (int i = cmin; i < cmax; i++){ ptemp[num++] = p[i]; if (i == right) isright = 1; } if (!(res2 == p[cmax-1]) ){ ptemp[num++] = res2; } if (isright == 1) return area(ptemp,num); else return ar - area(ptemp,num); } bool check(point P, point now) { line li; li.a = P; li.b = now; int sum = 0; point res; int cmin = -1,cmax; for (int i = 1; i <= N; i++){ if (line_make_point(li,line1[i],res)){ sum++; if (sum == 1){ res1 = res; cmin = i; } else{ res2 = res; cmax = i; } } } if ( cmp(getarea(cmin,cmax )-(ar/2.0) )==-1) return 1; return 0; } double getdis(point p,point q) { return sqrt((p.y-q.y)*(p.y-q.y) + (p.x-q.x)*(p.x-q.x)); } double trans(double x) { if(abs(x) < eps1) return abs(x); else return x; } void getlr(point P) { for (int i = 0; i < N; i++){ int isr = 0,isl = 0; for (int j = 0; j < N; j++){ if (j != i){ if (!(cmp(det(p[i]-P,p[j]-P) ) != -1)) isr = 1; else isl = 1; } } if (isr != 1){ right = i; } if (isl != 1)left = i; } } int main() { //freopen("input.txt","r",stdin); int T; scanf("%d",&T); int cas = 1; while (T--){ scanf("%d",&N); for (int i = 0; i < N; i++){ scanf("%lf %lf",&p[i].x,&p[i].y); if (i != 0){ line1[i].a = p[i-1]; line1[i].b = p[i]; } }ar = area(p,N); line1 .a = p[N-1]; line1 .b = p[0];//从第1条线一直到第N条线 point P; scanf("%lf %lf",&P.x,&P.y); point pr,pl; getlr(P); pr = p[right]; pl = p[left]; r = 1.0; l = 0; double res0; point resc; point now; int a7 = 60; while (a7--){ double mid = (r + l)/(2.0); now = pl + mid * (pr-pl); if (check(P,now)){ resc = now; r = mid; }else l = mid; } double dis = getdis(now,P); printf("Case #%d: %.4f %.4f\n",cas++,trans((now.x-P.x)/dis+eps),trans((now.y-P.y)/dis+eps)); } return 0; }
相关文章推荐
- UESTC1560 Division(四川2011年省赛 D,计算几何)
- Gym 101243.I - Land Division Gym - 101243I(计算几何 切割凸包)
- I - Land Division Gym - 101243I 计算几何 切割凸包
- 半平面交(UESTC 484,Division)
- uestc oj Justice is Given by Light(计算几何)
- Gym 101243 I Land Division[计算几何]
- 【计算几何】【分类讨论】Gym - 101243I - Land Division
- bzoj 1573 [Usaco2009 Open]牛绣花cowemb 计算几何 树状数组
- uva 190 Circle Through Three Points (计算几何) 面向对象的封装
- 二维计算几何基础
- hdu 1086:You can Solve a Geometry Problem too(计算几何,判断两线段相交,水题)
- 计算几何之判断两线段是否相交
- bzoj 1502 计算几何
- hdu 3320 计算几何(三维图形几何变换)
- H - 计算几何初步
- 计算几何模板存储
- POJ 1410 Intersection <计算几何(线段相交判断)>
- 平面计算几何模版集合
- uva5984(简单计算几何)
- 【jzoj5036】【原谅】【数学期望】【计算几何】