[NOI2005]月下柠檬树[计算几何(simpson)]

2024-03-24 09:40

本文主要是介绍[NOI2005]月下柠檬树[计算几何(simpson)],希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1502: [NOI2005]月下柠檬树

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 1169  Solved: 626
[Submit][Status][Discuss]

Description

Input

文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度)。第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的高度和每层的高度。第3行包含n个实数r1,r2,…,rn,表示柠檬树每层下底面的圆的半径。上述输入文件中的数据,同一行相邻的两个数之间用一个空格分隔。输入的所有实数的小数点后可能包含1至10位有效数字。

Output

输出1个实数,表示树影的面积。四舍五入保留两位小数。

Sample Input

2 0.7853981633
10.0 10.00 10.00
4.00 5.00

Sample Output

171.97

HINT

 

1≤n≤500,0.3

 

Source

 

求一棵树(圆锥加圆台组成)在平面上的投影的面积。

给定投影角度(0.3 < alpha <= pi/2)。

先来想想圆的投影是什么样子

这里写图片描述

还是他自己。

再想圆锥投影是什么样子

一个点加一个圆,并且有这个点与该圆的两条切线(该点在圆内部时没有切线)

再想圆台

两个圆,加上两个圆的外公切线组成的一坨图形。

不妨随意画一个。

这里写图片描述

好难画- -!

大概就转化成这个样子了。

观察这个图形…

轴对称啊- -!

这里写图片描述

首先AC长是圆心距,可求。

AI长是半径差,可求。

所以CI可求。

连接FC,观察△FAC

2*S△FAC=FG*AC=CI*AF

AF为半径,已知。

所以FG可求。

于是AG可求。

A点坐标已知,所以F点坐标已知。

E点,直接相似即可。

或者用射影定理求EF

概述图中,在Rt△ABC中,∠ABC=90°,BD是斜边AC上的高,则有射影定理如下:

 

BD²=AD·CD
AB²=AC·AD
BC²=CD·AC
#include<cmath>
#include<cstdio>
#include<algorithm>
#define pf(x) ((x)*(x))
using namespace std;
const int N=2000+5;
const double eps=1e-6;
typedef pair<double,double> point;
typedef pair<double,double> circle;
struct line{point s,t;double k,b;line(){}line(point _s,point _t){s=_s;t=_t;k=(s.second-t.second)/(s.first-t.first);b=s.second-s.first*k;}const double f(const double x){return k*x+b;}
};
int n,n1;double alpha,H[N];
point p;line L[N];circle C[N];
double lb=2e9,rb;
double sina,cosa,tana;
inline void add(const circle &a,const circle &b){n1++;sina=(a.second-b.second)/(b.first-a.first);cosa=sqrt(1-pf(sina));tana=sina/cosa;L[n1].s=make_pair(a.first+a.second*sina,a.second*cosa);L[n1].t=make_pair(b.first+b.second*sina,b.second*cosa);L[n1].k=-tana;L[n1].b=L[n1].s.second-L[n1].s.first*L[n1].k;
}
inline const double F(const double x){double re=0;for(int i=1;i<=n1;i++) if(x>=L[i].s.first&&x<=L[i].t.first) re=max(re,L[i].f(x));for(int i=1;i<=n;i++) if(x>=C[i].first-C[i].second&&x<=C[i].first+C[i].second) re=max(re,sqrt(pf(C[i].second)-pf(x-C[i].first)));return re;
}
inline const double simpson(const double l,const double r){double mid=(l+r)/2;return (F(l)+F(r)+4*F(mid))*(r-l)/6;
}
inline double asr(double l,double r,double eps,double last){double mid=(l+r)/2;double L=simpson(l,mid),R=simpson(mid,r);if(fabs(L+R-last)<=15*eps) return L+R+(L+R-last)/15;return asr(l,mid,eps/2,L)+asr(mid,r,eps/2,R);
}
inline int cmp(const double x){if(fabs(x)<eps) return 0;return x>0?1:-1;
}
int main(){scanf("%d%lf",&n,&alpha);for(int i=1;i<=n+1;i++) scanf("%lf",&H[i]),H[i]+=H[i-1];for(int i=1;i<=n;i++) scanf("%lf",&C[i].second);double ta=tan(alpha);p=make_pair(H[n+1]/ta,0);rb=max(rb,p.first);double x,r,l,h;C[n].first=H[n]/ta;x=C[n].first;r=C[n].second;lb=min(lb,x-r);rb=max(rb,x+r);if(x+r<p.first){l=pf(r)/(p.first-x);// 射影定理 h=sqrt(pf(r)-pf(l));L[++n1]=line(make_pair(x+l,h),p);}for(int i=n-1;i;i--){C[i].first=H[i]/ta;x=C[i].first;r=C[i].second;lb=min(lb,x-r);rb=max(rb,x+r);if(cmp(C[i+1].first-x-fabs(C[i+1].second-r))>0)//内含 add(C[i],C[i+1]);}printf("%.2lf\n",2*asr(lb,rb,eps,simpson(lb,rb)));return 0;
}

 

转载于:https://www.cnblogs.com/shenben/p/6850582.html

这篇关于[NOI2005]月下柠檬树[计算几何(simpson)]的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/841218

相关文章

使用C#代码计算数学表达式实例

《使用C#代码计算数学表达式实例》这段文字主要讲述了如何使用C#语言来计算数学表达式,该程序通过使用Dictionary保存变量,定义了运算符优先级,并实现了EvaluateExpression方法来... 目录C#代码计算数学表达式该方法很长,因此我将分段描述下面的代码片段显示了下一步以下代码显示该方法如

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

uva 10387 Billiard(简单几何)

题意是一个球从矩形的中点出发,告诉你小球与矩形两条边的碰撞次数与小球回到原点的时间,求小球出发时的角度和小球的速度。 简单的几何问题,小球每与竖边碰撞一次,向右扩展一个相同的矩形;每与横边碰撞一次,向上扩展一个相同的矩形。 可以发现,扩展矩形的路径和在当前矩形中的每一段路径相同,当小球回到出发点时,一条直线的路径刚好经过最后一个扩展矩形的中心点。 最后扩展的路径和横边竖边恰好组成一个直

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 1342 欧拉定理(计算几何模板)

题意: 给几个点,把这几个点用直线连起来,求这些直线把平面分成了几个。 解析: 欧拉定理: 顶点数 + 面数 - 边数= 2。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

uva 11178 计算集合模板题

题意: 求三角形行三个角三等分点射线交出的内三角形坐标。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <

XTU 1237 计算几何

题面: Magic Triangle Problem Description: Huangriq is a respectful acmer in ACM team of XTU because he brought the best place in regional contest in history of XTU. Huangriq works in a big compa

poj 3304 几何

题目大意:给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!。 解题思路:如果存在这样的直线,过投影相交点(或投影相交区域中的点)作直线的垂线,该垂线(也是直线)必定与每条线段相交,问题转化为问是否存在一条直线和所有线段相交。 若存在一条直线与所有线段相交,此时该直线必定经过这些线段的某两个端点,所以枚举任意两个端点即可。

POJ 2318 几何 POJ 2398

给出0 , 1 , 2 ... n 个盒子, 和m个点, 统计每个盒子里面的点的个数。 const double eps = 1e-10 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;}struct Point{double x , y

poj 2653 几何

按顺序给一系列的线段,问最终哪些线段处在顶端(俯视图是完整的)。 const double eps = 1e-10 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;}struct Point{double x , y ;Point(){}Po