zoj 1369
来源:互联网 发布:nginx与zookeeper 编辑:程序博客网 时间:2024/06/06 02:08
裸的半平面交。
这个题没说输入是顺时针还是逆时针,可以用面积判断,多边形面积如果是顺时针,面积为负,改变下方向即可。
粘两个模板。
code 1:
//书27页 #include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>using namespace std;#define MAXN 1510const double EPS=1e-12;//半平面为向量表示,平面维宇向量左侧struct point{ double x,y; } convex[MAXN];struct line{ point a,b; double ang; //角度(弧度) }l[MAXN],st[MAXN];int n,ccnt; double operator *(const point &x,const point &y)//向量叉乘3 { return x.x*y.y-x.y*y.x; } point operator -(point x,const point &y) //向量减法 { x.x-=y.x,x.y-=y.y; return x; } point operator *(const line &x,const line &y)//直线求交点 { double a1=(y.b-x.a)*(y.a-x.a),a2=(y.a-x.b)*(y.b-x.b); point r; r.x=(x.a.x*a2+x.b.x*a1)/(a2+a1); r.y=(x.a.y*a2+x.b.y*a1)/(a2+a1); return r; } bool operator ==(const point &a,const point &b)//判断共点 { return fabs(a.x-b.x)<EPS&&fabs(a.y-b.y)<EPS; } bool operator <(const line &x,const line &y)//为极角排序重载的运算符{ if(fabs(x.ang-y.ang)<EPS) return (y.b-x.a)*(x.b-y.a)>EPS; return x.ang<y.ang;}bool judgeout(const line &x,const point &p)//判断点和平面的关系{return (p-x.a)*(x.b-x.a)>EPS; }bool parellel(const line &x,const line &y)//判断两个向量是否平行{ return fabs((x.b-x.a)*(y.b-y.a))<-EPS; }void inputdata(){ scanf("%d",&n); scanf("%lf%lf",&l[0].b.x,&l[0].b.y); l[n-1].a.x=l[0].b.x,l[n-1].a.y=l[0].b.y; for(int i=1;i<n;i++) { scanf("%lf%lf",&l[i].b.x,&l[i].b.y); l[i-1].a.x=l[i].b.x,l[i-1].a.y=l[i].b.y; } for(int i=0;i<n;i++) l[i].ang=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);}double hplaneintersection(){ int top=1,bot=0; sort(l,l+n); //极角排序 int tmp=1; for(int i=1;i<n;++i) if(l[i].ang-l[i-1].ang>EPS) l[tmp++]=l[i];//去重 n=tmp; st[0]=l[0],st[1]=l[1]; for(int i=2;i<n;++i) { if(parellel(st[top],st[top-1])||parellel(st[bot],st[bot+1])) return 0; while(bot<top&&judgeout(l[i],st[top]*st[top-1])) top--; while(bot<top&&judgeout(l[i],st[bot]*st[bot+1])) bot++; st[++top]=l[i]; } while((bot<top&&judgeout(st[bot],st[top]*st[top-1]))) top--; while((bot<top&&judgeout(st[top],st[bot]*st[bot+1])))bot++; if(top<bot+1) return 0.00; st[++top]=st[bot]; ccnt=0; for(int i=bot;i<top;i++) convex[ccnt++]=st[i]*st[i+1]; double ans=0; convex[ccnt]=convex[0]; for(int i=0;i<ccnt;i++) ans+=convex[i]*convex[i+1]; return ans/2;}double chackdirection(){ double ans=0; for(int i=0;i<n;++i) ans+=l[i].a*l[i].b; return ans;}void changedirection(){ for(int i=0;i<n;++i) swap(l[i].a,l[i].b);}int main(){ int t; scanf("%d",&t); while(t--) { inputdata(); if(chackdirection()<0) changedirection(); printf("%.2f\n",hplaneintersection()); } return 0;}
code 2:
/*半平面交。解释下这个算法哈,其实用笔模拟一下就懂了。它是在一层一层缩小这个区域。外层循环是用每一条边,筛选能看到它的点(或者说是内层形成的边吧),如果看不到(也就是内层有边得两点在他的两侧),那么就求这条边和当前内层循环边的交点作为核的点。交点是肯定能看到的啦。所以内层循环结束一次,点集就要变一次。*/#include <queue>#include <stack>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <iostream>#include <limits.h>#include <string.h>#include <string>#include <algorithm>using namespace std;const int MAX = 1510;struct point{ double x,y;};point p[MAX],s[MAX];const double eps = 1e-6;bool dy(double x,double y){return x > y + eps;}// x > y bool xy(double x,double y){return x < y - eps;}// x < y bool dyd(double x,double y){ return x > y - eps;}// x >= y bool xyd(double x,double y){return x < y + eps;} // x <= y bool dd(double x,double y) {return fabs( x - y ) < eps;} // x == ydouble crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向 {return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);}point l2l_inst_p(point u1,point u2,point v1,point v2){point ans = u1;double t = ((u1.x - v1.x)*(v1.y - v2.y) - (u1.y - v1.y)*(v1.x - v2.x))/((u1.x - u2.x)*(v1.y - v2.y) - (u1.y - u2.y)*(v1.x - v2.x));ans.x += (u2.x - u1.x)*t;ans.y += (u2.y - u1.y)*t;return ans;}void change_wise(point p[],int n){for(int i=0; i<n/2; i++)swap(p[i],p[n-i-1]);}void inst_hp(point p[],int n,point s[],int &len){point tp[MAX];p[n] = p[0];for(int i=0; i<=n; i++)tp[i] = p[i];int cp = n,tc;for(int i=0; i<n; i++){tc = 0;for(int k=0; k<cp; k++){if( xyd(crossProduct(p[i],p[i+1],tp[k]),0.0) )// 顺时针的话是dyd s[tc++] = tp[k];if( xy(crossProduct(p[i],p[i+1],tp[k])* crossProduct(p[i],p[i+1],tp[k+1]),0.0) )s[tc++] = l2l_inst_p(p[i],p[i+1],tp[k],tp[k+1]);}s[tc] = s[0];for(int k=0; k<=tc; k++)tp[k] = s[k];cp = tc;}len = cp;}double area_polygon(point p[],int n){double s = 0.0;for(int i=0; i<n; i++)s += p[(i+1)%n].y * p[i].x - p[(i+1)%n].x * p[i].y;return s/2.0;}int main(){int len,ncases,n;scanf("%d",&ncases);while( ncases-- ){scanf("%d",&n);for(int i=0; i<n; i++)scanf("%lf%lf",&p[i].x,&p[i].y);double area = area_polygon(p,n);if( xyd(area,0.0) ) change_wise(p,n);inst_hp(p,n,s,len);double ans = area_polygon(s,len);printf("%.2lf\n",fabs(ans));}return 0;
- zoj 1369
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- ZOJ
- 网络字节序与主机字节序的转换
- 通过hudson API 启动构建并且指定revision版本
- 牛人编写的ICE相关博客
- 维特比算法——寻找最可能的隐藏状态序列
- 3小时上手微信公众帐号开发
- zoj 1369
- TypeError: 'str' object is not callable
- Apache common-pool, common-dbcp源码解读与对象池原理剖析
- Oracle常用查看表结构命令
- Java发送邮件简单实例
- 基于DirectFB的framebuffer底层驱动及应用程序架构原理分析
- 怎么在Datagridview查询的结果中进行修改-我只是感慨您从那学的??
- QListWidget的基本使用
- 理解ThreadLocal