计算几何-UESTC 484 Division
来源:互联网 发布:2000年人口普查数据 编辑:程序博客网 时间:2024/04/27 03:49
题意:给一个萌点,找到经过这个萌点的射线可以平分多边形。
题解:
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 0x3f3f3f3fusing 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[n] = 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[N].a = p[N-1]; line1[N].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;}
0 0
- 计算几何-UESTC 484 Division
- Gym 101243 I Land Division[计算几何]
- 半平面交(UESTC 484,Division)
- UESTC1560 Division(四川2011年省赛 D,计算几何)
- UESTC oj 797 Eh? Beautiful Stone!(计算几何)
- uestc oj Justice is Given by Light(计算几何)
- UESTC 1170 红与蓝 计算几何、贪心、红蓝点对
- UESTC oj Division by 3 数论
- UESTC Summer Training #5 Division I
- UESTC Summer Training #10 Division I
- The 14th UESTC Programming Contest Final I - Intersection 计算几何、积分、精度
- GPA计算 UESTC
- 计算几何几何函数库
- 计算几何-几何库
- 计算几何
- 计算几何
- 计算几何
- 计算几何
- java okhttp 网络请求
- 鹿鼎记随笔
- 10817 - Headmaster's Headache
- NVSRAM:不再需要电池的非易失性存储方案
- Winform控件之分组类控件
- 计算几何-UESTC 484 Division
- 类handler
- 九度oj 1349 数字在排序数组中出现的次数
- 3d数学基础-向量相关操作-用C++实现
- 为 checkbox 添加事件,使选中和非选中时改变其他几个checkbox的可选状态
- 浅谈root原理以及已知漏洞的分析
- cordova webview的使用
- 管理软件的痛处
- 【c#第五次作业】测试 Html2Article 并添加保存功能