一堆圆台平行光的投影

在草稿纸上画一下,发现对于一个圆,它投影完还是一个半径不变的圆。

定义树的轴在投影平面上经过的点为原点,定一个正方向,建立平面直角坐标系,

能发现,对于一个半径为\(r\),高度为\(h\)的圆,投影到平面上是圆心坐标为\((cot(\alpha)h, 0)\),半径为\(r\)的圆

想象有一个水平的平面,竖直向上移,可以把树切出一堆圆,对于这些圆,把它们投影求个并就是答案

对于每个圆台,它一堆圆的并就是先求上下两个面的圆的投影,再对投影求外公切线,围成的图形

如图,就是\(BEHDGF\)围成的面积

注意对于两个圆的内含或内切关系,是没有切线的

对于树顶,我们把它当做一个半径为\(0\)的圆

那么大概可以画成这样

首先因为它是轴对称的,所以只用算出x轴上方的

但是这面积并怎么求呢?求出所有交点?

这个图挺特殊,所以可以对不规则的函数下方面积考虑使用自适应simpson

然后就做完了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath> const double eps = 1e-6;
const double STOP = 15;
const int MAXN = 510;
double xs[MAXN], rs[MAXN], theta;
double tx1[MAXN], ty1[MAXN], tx2[MAXN], ty2[MAXN];
int bak;
inline double absx(double x) { return x < 0 ? -x : x; }
inline double sqrx(double x) { return x * x; }
int n;
double f(double at) {
double res = 0;
for (int i = 1; i <= n; ++i) {
double t = absx(xs[i] - at);
if (t < rs[i])
res = std::max(res, sqrt(sqrx(rs[i]) - sqrx(t)));
}
for (int i = 1; i <= bak; ++i) {
if (tx1[i] - eps <= at && at <= tx2[i] + eps) {
double tanx = (ty2[i] - ty1[i]) / (tx2[i] - tx1[i]);
res = std::max(res, ty1[i] + tanx * (at - tx1[i]));
}
}
return res;
}
inline double calc(double l, double mid, double r) {
return (l + r + mid * 4) / 6;
}
double simpson(double l, double r, double eps, double ll, double midv, double lr) {
// if (absx(r - l) < 0.1) return 213213;
const double lans = calc(ll, midv, lr) * (r - l);
const double mid = (l + r) / 2;
const double lmid = (l + mid) / 2, rmid = (mid + r) / 2;
const double lmidv = f(lmid), rmidv = f(rmid);
const double lv = calc(ll, lmidv, midv) * (mid - l);
const double rv = calc(midv, rmidv, lr) * (r - mid);
// std::cout << "SIMP " << l << " " << r << " " << eps << " " << lans << " " << lv << " " << rv << std::endl;
if (absx(lv + rv - lans) <= eps * STOP) return lans;
return simpson(l, mid, eps / 2, ll, lmidv, midv) +
simpson(mid, r, eps / 2, midv, rmidv, lr);
}
int main() {
double L = 1e10, R = -1e10;
scanf("%d%lf", &n, &theta); ++n;
const double transform = 1 / tanl(theta);
double now = 0, t;
for (int i = 1; i <= n; ++i) {
scanf("%lf", &t);
now += t;
xs[i] = now * transform;
}
for (int i = 1; i != n; ++i) scanf("%lf", rs + i);
for (int i = 1; i <= n; ++i) {
L = std::min(L, xs[i] - rs[i]);
R = std::max(R, xs[i] + rs[i]);
}
rs[n] = 0;
for (int i = 1; i != n; ++i) {
if (absx(xs[i] - xs[i + 1]) < absx(rs[i + 1] - rs[i]) + eps) continue;
const double sina = (rs[i + 1] - rs[i]) / (xs[i + 1] - xs[i]);
if (1 - sqrx(sina) < eps) continue;
const double cosa = sqrt(1 - sqrx(sina));
++bak;
tx1[bak] = xs[i] - sina * rs[i];
ty1[bak] = cosa * rs[i];
tx2[bak] = xs[i + 1] - sina * rs[i + 1];
ty2[bak] = cosa * rs[i + 1];
}
printf("%.2lf\n", simpson(L, R, eps, f(L), f((L + R) / 2), f(R)) * 2);
return 0;
}

1502: [NOI2005]月下柠檬树的更多相关文章

  1. BZOJ 1502: [NOI2005]月下柠檬树 [辛普森积分 解析几何 圆]

    1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1070  Solved: 596[Submit][Status] ...

  2. 1502: [NOI2005]月下柠檬树 - BZOJ

    Description Input 文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度).第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的 ...

  3. [BZOJ 1502] [NOI2005] 月下柠檬树 【Simpson积分】

    题目链接: BZOJ - 1502 题目分析 这是我做的第一道 Simpson 积分的题目.Simpson 积分是一种用 (fl + 4*fmid + fr) / 6 * (r - l) 来拟合 fl ...

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

    1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1169  Solved: 626[Submit][Status] ...

  5. [NOI2005]月下柠檬树

    题意 F.A.Qs Home Discuss ProblemSet Status Ranklist Contest 入门OJ ModifyUser  autoint Logout 捐赠本站 Probl ...

  6. 【BZOJ1502】[NOI2005]月下柠檬树 Simpson积分

    [BZOJ1502][NOI2005]月下柠檬树 Description 李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树 ...

  7. 【bzoj 1502】月下柠檬树

    月下柠檬树 题意 求n个圆与他们的公切线的定积分. 解法 求出圆的公切线就可以了. 特别坑的一点 : 最两端的圆,有可能会被其他的圆所包含,所以要重新求一下最左端与最右端. 比较坑的一点 : 精度要设 ...

  8. 5.21 省选模拟赛 luogu P4207 [NOI2005]月下柠檬树 解析几何 自适应辛普森积分法

    LINK:月下柠檬树 之前感觉这道题很鬼畜 实际上 也就想到辛普森积分后就很好做了. 辛普森积分法的式子不再赘述 网上多的是.值得一提的是 这道题利用辛普森积分法的话就是一个解析几何的问题 而并非计算 ...

  9. BZOJ1502:[NOI2005]月下柠檬树——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=1502 https://www.luogu.org/problemnew/show/P4207 李哲 ...

随机推荐

  1. Hadoop简介及架构

    狭义上来说,hadoop就是单独指代hadoop这个软件, 广义上来说,hadoop指代大数据的一个生态圈,包括很多其他的软件 2.hadoop的历史版本介绍 0.x系列版本:hadoop当中最早的一 ...

  2. Windows下使用SVN版本控制工具

    一.SVN工作原理 SVN(SubVersion)的基本工作思路是这样的:在一台服务器上建立一个源代码库,库里可以存放许多不同项目的源程序,由源代码库管理员统一管理这些源程序. 每个用户在使用源代码库 ...

  3. Postman之简单使用

    前提:已获得接口文档 / 抓包数据 1.启动Postman 直接在这个页面输入数据(不用管其他的地方!!!) 2.按照接口文档填入 注意蓝色框中的数据 请求方式:POST(几乎都是使用POST/GET ...

  4. Python应用RabbitMQ教程

    介绍 RabbitMQ是一个消息代理.它的工作就是接收和转发消息.你可以把它想像成一个邮局:你把信件放入邮箱,邮递员就会把信件投递到你的收件人处.在这个比喻中,RabbitMQ就扮演着邮箱.邮局以及邮 ...

  5. hadoop批量命令脚本xcall.sh及jps找不到命令解决

    1.xcall.sh批量命令脚本: #!/bin/bash params=$@ i=128 for (( i=128 ; i <= 131 ; i = $i + 1 )) ; do echo = ...

  6. Qt 按键键值 与 相关字符串 的映射表(转)

    Qt快捷键 映射     "Esc",/*Qt::Key_Escape 0x01000000 */ "Tab",/*Qt::Key_Tab 0x01000001 ...

  7. FTP服务器上传,下载文件

    public class FtpUtil { /** * * @param host FTP服务器地址 * @param port FTP服务器端口 * @param username FTP登录账号 ...

  8. Vue项目里添加特殊字体或 某些字体乱码的问题

    问题:有个西藏的项目因使用藏文,而出现乱码 (一开始不乱的,不知道后台怎么处理...后来不知道为啥,前端乱码了) 解决:字体ttf 格式已下载,在项目中全局引入了 @font-face { font- ...

  9. 查询SAP数据库表的大小

    事物代码DB02 Perfomrmance->Additional Functions->SQL Command Editor->写数据表->执行 select bytes/1 ...

  10. shell脚本中的日期处理

    Ps:这篇文章只是为了做个分类,以后有看到比较好的时间处理命令都会列在这里,您如果有什么好的时间处理命令,可以评论中添加,我会定期查看更新,谢谢! 1.定义一个参数DATE_TODAY,用于记录当天时 ...