HDOJ 4368
来源:互联网 发布:淘宝打字客服容易吗 编辑:程序博客网 时间:2024/05/19 17:57
题意:给一个山脉,高低起伏,问向某一个方向旋转一个角度后(角度绝对值属于[0.0,80.0]),所能盛水的容量。
题解:向右转还是向左转差别不大,只需要将山脉reverse就行了。现在考虑向右转,从左往右遍历顶点,以该顶点(设为i)为起始点向右发出一条水平射线,与山脉某一条边碰撞(记为j),在这射线之下所能盛水的面积就等于射线与山脉所组成梯形减去这期间山脉的面积。但还要从记录的这条边的顶点处往左发出一条射线,与山脉某条边k碰撞,这条新射线会与原射线形成一个小梯形(也可能是平行四边形),这部分区域没有计算,所以还应加上。另外,遍历结点的指针就可以直接跳转到j了,因为i到j的区域面积已经计算完了。如此,遍历一遍就可以得出结果。
PS: 打代码速度还是慢了些,最后提交是17:00:37秒,out of contest time 囧,结果赛下一交成为第一个A的,坑爹啊。
#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>using namespace std;#define sign(x) ((x)>eps?1:((x)<-eps?(-1):(0))) //符号函数const double eps=1e-8;const double PI=acos(-1.0);const double inf=1e20;int n;struct point{ double x,y; point(){} point(double _x,double _y){x=_x,y=_y;}};struct seg{ point a,b; seg(){} seg(point _a,point _b){a=_a,b=_b;}};point L,R,po[20010];seg so[20010];inline double dist(point a,point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}void counter (double &x,double &y,double th){//绕原点逆时针旋转th弧度,顺时针则传入-th double tx=x,ty=y; x=tx*cos(th)-ty*sin(th); y=tx*sin(th)+ty*cos(th); return;}point R_rotata(point p,double ang){ point q; ang=ang*PI/180.0; q.x=p.x-R.x;q.y=p.y; counter(q.x,q.y,ang); q.x+=R.x; return q;}double xmult(double x1,double y1,double x2,double y2){ return x1*y2-x2*y1;}point line_intersection(seg u,seg v){ double a1=u.b.y-u.a.y,b1=u.a.x-u.b.x; double c1=u.b.y*(-b1)-u.b.x*a1; double a2=v.b.y-v.a.y,b2=v.a.x-v.b.x; double c2=v.b.y*(-b2)-v.b.x*a2; double D=xmult(a1,b1,a2,b2); return point(xmult(b1,c1,b2,c2)/D,xmult(c1,a1,c2,a2)/D);}int findleft(point p,int k,point &q){ int i; for(i=k;i>=0;i--) { if(so[i].b.y>p.y-eps) break; } if(i<0) return i; else if(i%2==1) { q=line_intersection(seg(p,point(p.x-1.0,p.y)),so[i]); return i;//与右边相遇 } else { q=line_intersection(seg(p,point(p.x-1.0,p.y)),seg(so[i].b,so[i+1].b)); return i;//与头顶相遇 }}int findright(point p,int k,point &q){ int i; for(i=k;i<n;i++) { if(so[i].b.y>p.y-eps) break; } if(i>=n) return i; else { q=line_intersection(seg(p,point(p.x+1.0,p.y)),so[i]); return i; }}double h[10010];int main(){ int num; double angle; while(scanf("%d%lf",&num,&angle)!=EOF) { n=num*2; R.x=(double)num,R.y=0; for(int i=0;i<num;i++) { scanf("%lf",&h[i]); } if(angle>eps) { reverse(h,h+num); angle=-angle; } for(int i=0;i<num;i++) { po[2*i].x=(double)i; po[2*i+1].x=i+1.0; po[2*i].y=po[2*i+1].y=h[i]; } if(angle<-eps) { double ans=0; for(int i=0;i<n;i++) { so[i].a=R_rotata(point(po[i].x,0.0),angle); so[i].b=R_rotata(po[i],angle); } point q1,q2; int i,j,k,tp; for(i=0;i<n;) { j=findright(so[i].b,i+1,q1); if(j>=n) { i++; continue; } ans=ans+(dist(so[i].a,so[i].b)+dist(so[j].a,q1))*(po[j].x-po[i].x)/2.0; if(i&1) for(tp=i+1;tp<j;tp+=2) ans-=po[tp].y; else for(tp=i;tp<j;tp+=2) ans=ans-po[tp].y; k=findleft(so[j].b,i-1,q2); if(k<0) { i=j; continue; } if(k&1) ans=ans+dist(q2,so[j].b)*(so[j].b.y-so[i].b.y); else ans=ans+(dist(q1,so[i].b)+dist(q2,so[j].b))*(so[j].b.y-so[i].b.y)/2.0; i=j; } printf("%.2lf\n",ans); } else { double ans=0; for(int i=0;i<n;i++) { so[i].a=point(po[i].x,0.0); so[i].b=po[i]; } point q1,q2; int i,j,k,tp; for(i=1;i<n;) { j=findright(so[i].b,i+1,q1); if(j>=n) { i+=2; continue; } ans=ans+(dist(so[i].a,so[i].b)+dist(so[j].a,q1))*(po[j].x-po[i].x)/2.0; for(tp=i+1;tp<j;tp+=2) ans-=po[tp].y; k=findleft(so[j].b,i-1,q2); if(k<0) { i=j+1; continue; } ans=ans+dist(q2,so[j].b)*(so[j].b.y-so[i].b.y); i=j+1; } printf("%.2lf\n",ans); } } return 0;}
- HDOJ 4368
- HDOJ
- hdoj
- hdoj
- HDOJ
- hdoj 1568 && hdoj 5344 && hdoj 5444
- HDOJ 2176
- Hdoj--1272
- hdoj 1003
- hdoj 1005
- hdoj 1030
- hdoj 2154
- hdoj 2100
- HDOJ 1106
- hdoj 1257
- hdoj 1159
- hdoj 1160
- hdoj 3283
- #if 0/#if 1 ... #endif”的作用
- Linux下创建和删除用户 切换用户
- PBRT阅读:第七章 采样和重构 第7.2-7.3节
- poj 2828 树状数组
- Android Dialog大全
- HDOJ 4368
- PBRT阅读:第一章 1.2 具有照片真实感的渲染和光线追踪算法
- 新版接口access token的有效期
- 5 个开源 3D 建模/渲染工具
- PBRT阅读:第六章 相机模型
- Firefox OS将掀起100美元智能手机浪潮
- PBRT阅读:第五章 颜色和辐射度学 第5.1节
- 前端开发工程师目前局势是非常辛苦的
- windows 下php 开发环境的多种搭建方式