计算几何 val.3
计算几何 val.3
自适应辛普森法
可以用来求多边形的面积并(圆也行)
定积分
定积分的几何意义是函数的曲线上 \(x\) 的一段区间与 \(x\) 轴围成的曲边梯形的带符号面积
表示法为
\]
引入
计算方法:
分成一堆小区间
\[\int_{a}^{b} f(x) \mathrm{d} x=\lim _{n \rightarrow \infty} \sum_{i=1}^{n} \frac{b-a}{n} f\left(a+\frac{b-a}{n} i\right)
\]牛顿-莱布尼茨公式
如果
\[F^{\prime}(x)=f(x)
\]则
\[\int_{a}^{b} f(x) \mathrm{d} x=F(b)-F(a)
\]这个可以求:\(\int_a^b(\frac 1 x)dx = \ln |b|-\ln |a|\)
这也是连接定积分和不定积分的桥梁
对于一些难求的积分,我们可以用数值积分来求,其中常用的是自适应辛普森积分
辛普森公式
此公式用二次函数来拟合原函数
\]
\]
\]
提出\(b-a\),
\]
\]
\]
\]
\]
于是可以得到公式:
\]
当然,对于二次函数这是对的
对于其余情况,\(b-a\)越小,上面两个式子越接近
这种情况下我们就要调整精度
处理精度
考虑把一段长的区间分成很多段小区间求和
可是分的太少了不能满足精度要求,太多了会TLE
那么考虑什么时候停止分下去呢?
对于当前区间,求出\(ans=simpson(l,r),mid=\frac{l+r}{2}\)
然后求出对于下一层区间的答案:\(ls=simpson(l,mid),rs=simpson(mid,r)\)
注意此处mid右边不用加一,不是整数域
如果\(|ls+rs-ans|<eps\),即满足精度要求,可以停止二分
考虑到一些小的误差加起来很大,eps要设的比题目要求的小一点
而且下一层的eps是上一层的二分之一,因为有两个
代码实现
double F(...){
...
}
double simpson(double l,double r){
double mid=(l+r)/2.0;
return (r-l)/6.0*(F(l)+4.0*F(mid)+F(r));
}
double solve(double l,double r,double ans,double eps){
double mid=(l+r)/2.0;
double ls=simp(l,mid),rs=simp(mid,r);
if(fabs(ls+rs-ans)<eps*15) return ls+rs+(ls+rs-ans)/15;
else return solve(l,mid,ls,eps*0.5)+solve(mid,r,rs,eps*0.5);
}
等一下,好像实现和上面的思路不同?
if(fabs(ls+rs-ans)<eps*15) return ls+rs+(ls+rs-ans)/15;
这\(15\)是个啥东西?
噔 噔 咚
论证,请(绝望)
最后移一下项就好了,得到ls+rs+(ls+rs-ans)/15
模板
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define db double
using namespace std;
db a,b,c,d,l,r;
db F(db x){
return (c*x+d)/(a*x+b);
}
db simp(db l,db r){
db mid=(l+r)/2.0;
return (r-l)/6.0*(F(l)+4.0*F(mid)+F(r));
}
db solve(db l,db r,db ans,db eps){
db mid=(l+r)/2.0;
db ls=simp(l,mid),rs=simp(mid,r);
if(fabs(ls+rs-ans)<eps*15) return ls+rs+(ls+rs-ans)/15;
else return solve(l,mid,ls,eps*0.5)+solve(mid,r,rs,eps*0.5);
}
int main(){
scanf("%lf%lf%lf%lf%lf%lf",&a,&b,&c,&d,&l,&r);
printf("%.6f",solve(l,r,simp(l,r),1e-8));
return 0;
}
时间复杂度
精度不能开太小,开要求精度再多2~3位都很稳
练习
找不到题啊。。
面积并:
\]
\(f(x)\)为一条垂直于x轴的线的覆盖的长度
然后就可以用辛普森积分算了
算\(f\)的话可以求出所有交点,按上点排序,O(n)枚举计算出下一条线是否和当前有交点,并计算长度
90分代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define db double
int n;
const int N = 1001;
db x[N],y[N],r[N];
const double eps=1e-3;
struct node{
db u,d;
}p[N];
int tp;
int cmp(const node &aa,const node &bb){
return aa.u<bb.u;
}
db F(db pos){
tp=0;
for(int i=1;i<=n;i++){
if(pos>=x[i]-r[i]&&pos<=x[i]+r[i]){
p[++tp].u=y[i]-sqrt(r[i]*r[i]-(x[i]-pos)*(x[i]-pos));
p[tp].d=y[i]+sqrt(r[i]*r[i]-(x[i]-pos)*(x[i]-pos));
}
}
sort(p+1,p+tp+1,cmp);
db nu=p[1].u,nd=p[1].d,ans=0;
for(int i=2;i<=tp;i++){
if(p[i].u<=nd){
nd=max(nd,p[i].d);
}else{
ans+=(nd-nu);
nu=p[i].u,nd=p[i].d;
}
}
ans+=(nd-nu);
return ans;
}
db simp(db l,db r){
db mid=(l+r)*0.5;
return (r-l)/6.0*(F(l)+4.0*F(mid)+F(r));
}
db solve(db l,db r,db ans,db eps){
db mid=(l+r)*0.5;
db ls=simp(l,mid),rs=simp(mid,r);
if(fabs(ls+rs-ans)<15.0*eps) return ls+rs+(ls+rs-ans)/15.0;
else return solve(l,mid,ls,eps*0.5)+solve(mid,r,rs,eps*0.5);
}
int main(){
scanf("%d",&n);
db ml=1926081700.1,mr=-1926081700.1;
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf",&x[i],&y[i],&r[i]);
ml=min(x[i]-r[i],ml);
mr=max(mr,x[i]+r[i]);
}
printf("%.3f",solve(ml,mr,simp(ml,mr),eps));
return 0;
}
最后一个点被卡了,认识到此算法只能用来骗分。艹
闵可夫斯基和
空间中点集的和
有一些性质,比如,凸包之间的闵可夫斯基和一定是凸包
求凸包之间的闵可夫斯基和的方法:把两个凸包的每一条向量都抠出来,按照极角序排序构成新凸包
实现方法:
pot P={-inf,-inf},Q={-inf,-inf},R={-inf,-inf};
n=read();
for(int i=1;i<=n;i++)
{
a[i].x=read();a[i].y=read();
if(dcmp(a[i].y-P.y)==0&&dcmp(a[i].x-P.x)<0)P=a[i];
if(dcmp(a[i].y-P.y)>0)P=a[i];
if(i!=1)f[++cnt]=a[i]-a[i-1];if(i==n)f[++cnt]=a[1]-a[i];
}
n=read();
for(int i=1;i<=n;i++)
{
b[i].x=read();b[i].y=read();
if(dcmp(b[i].y-Q.y)==0&&dcmp(b[i].x-Q.x)<0)Q=b[i];
if(dcmp(b[i].y-Q.y)>0)Q=b[i];
if(i!=1)f[++cnt]=b[i]-b[i-1];if(i==n)f[++cnt]=b[1]-b[i];
}
n=read();
for(int i=1;i<=n;i++)
{
c[i].x=read();c[i].y=read();
if(dcmp(c[i].y-R.y)==0&&dcmp(c[i].x-R.x)<0)R=c[i];
if(dcmp(c[i].y-R.y)>0)R=c[i];
if(i!=1)f[++cnt]=c[i]-c[i-1];if(i==n)f[++cnt]=c[1]-c[i];
}
sort(f+1,f+cnt+1,cmp);
pot k=P+Q+R;p[++tot]=k;
for(int i=1;i<=cnt;i++)
{
k=k+f[i];
if(i!=cnt&&dcmp(f[i].x*f[i+1].y-f[i].y*f[i+1].x)==0)continue;
p[++tot]=k;
}
tot--;k=p[1];
没有例题,抱歉
Pick定理
结论
在一个平面直角坐标系内,以整点为顶点的简单多边形,设其内部整点数为\(a\),边上(包括顶点)的整点数为\(b\),则它的面积为\(a+\frac b 2 -1\)
证明:
例题
=模板
边上的格点数=|dx|和|dy|的最大公约数
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int ol,x1,x2,x3,ya,yb,yc;
int gcd(int x,int y) {
return y==0?x:gcd(y,x%y);
}
int area() {
return abs((x2-x1)*(yc-ya)-(x3-x1)*(yb-ya))/2;
}
int cal(int x1,int ya,int x2,int yb) {
int dx,dy;
if(x1<x2)dx=x2-x1;
else dx=x1-x2;
if(ya<yb)dy=yb-ya;
else dy=ya-yb;
return gcd(dx,dy);
}
int main() {
while(scanf("%d%d%d%d%d%d",&x1,&ya,&x2,&yb,&x3,&yc)) {
if(!x1&&!x2&&!x3&&!ya&&!yb&&!yc)break;
ol=cal(x1,ya,x2,yb)+cal(x2,yb,x3,yc)+cal(x3,yc,x1,ya);
printf("%d\n",area()-ol/2+1);
}
return 0;
}
后记
其实 val.2 比 val.3 难且重要
但是不重要不代表不学呀
辛普森积分还是挺实用的,我觉得
没有val.4了,最多写写做题记录
计算几何 val.3的更多相关文章
- 计算几何 val.2
目录 计算几何 val.2 几何单位结构体板子 旋转卡壳 基础概念 求法 模板 半平面交 前置芝士:线段交 S&I算法 模板 最小圆覆盖 随机增量法 时间复杂度 模板 后记 计算几何 val. ...
- 计算几何 val.1
目录 计算几何 val.1 向量的点积 向量的叉积 一种奇怪的三角剖分求面积 凸包 点绕点旋转 后记 计算几何 val.1 本文并不是入门文章,供有高中数学基础的阅读 主要写一些重要的点和注意事项吧 ...
- ACM 计算几何中的精度问题(转)
http://www.cnblogs.com/acsmile/archive/2011/05/09/2040918.html 计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模 ...
- POJ 1066 Treasure Hunt(计算几何)
题意:给出一个100*100的正方形区域,通过若干连接区域边界的线段将正方形区域分割为多个不规则多边形小区域,然后给出宝藏位置,要求从区域外部开辟到宝藏所在位置的一条路径,使得开辟路径所需要打通的墙壁 ...
- POJ 2318 TOYS(计算几何)
题目大意:有一个矩形盒子,盒子里会有一些木块线段,并且这些线段是按照顺序给出的,有n条线段,把盒子分层了n+1个区域,然后有m个玩具,这m个玩具的坐标是已知的,问最后每个区域有多少个玩具 解题思路:因 ...
- TOYS - POJ 2318(计算几何,叉积判断)
题目大意:给你一个矩形的左上角和右下角的坐标,然后这个矩形有 N 个隔板分割成 N+1 个区域,下面有 M 组坐标,求出来每个区域包含的坐标数. 分析:做的第一道计算几何题目....使用叉积判断方 ...
- POJ 1556 计算几何+最短路
代码1: #include<iostream> #include<stdio.h> #include<string> #include<string.h> ...
- 【BZOJ5316】[JSOI2018]绝地反击(网络流,计算几何,二分)
[BZOJ5316][JSOI2018]绝地反击(网络流,计算几何,二分) 题面 BZOJ 洛谷 题解 很明显需要二分一个答案. 那么每个点可以确定的范围就是以当前点为圆心,二分出来的答案为半径画一个 ...
- POJ - 2031 Building a Space Station(计算几何+最小生成树)
http://poj.org/problem?id=2031 题意 给出三维坐标系下的n个球体,求把它们联通的最小代价. 分析 最小生成树加上一点计算几何.建图,若两球体原本有接触,则边权为0:否则边 ...
随机推荐
- NFS介绍、服务端安装配置、NFS配置选项
6月21日任务 14.1 NFS介绍14.2 NFS服务端安装配置14.3 NFS配置选项 14.1 NFS介绍 14.2 NFS服务端安装配置 1.首先需要2台机器,一台是服务端,一台是客户端,分别 ...
- 【项目管理】Mybatis-Generator之最完美配置详解
今天看到了一篇总结特别详细的关于Mybatis-Generator配置文件的文章,特转载进行记录学习使用. 先附上原文地址链接:张思全----全哥文章 <?xml version="1 ...
- 客户端加载文本数据到mysql数据库表(数据导入和导出)
load data local infile "文件绝对路径" into table 表名; 如果指定了LOCAL,则文件会被客户主机上的客户端读取,并被发送到服务器 如果要导出表 ...
- luogu P5414 [YNOI2019]排序 |动态规划
题目描述 对于一个数列{7, 1, 2, 3}进行排序,我们可以把7 从头移动到尾.但是这个操作的成本是7,并不是最佳的.最佳的排序方式是将连续的1.2.3 移动到7 的前面.这样的话,总的操作成本就 ...
- SX1276/SX1278和SXSX1262的详细参数对比
SX1276/SX1278和SX1262的对比 SX1262是Semtech公司新推出的一款sub-GHz无线收发器.SX1262芯片最大的买点是它的低功耗和超远距离的传输.SX1262接收电流 ...
- PXE+Kickstart网络装机(Centos6.5版本)
1.原理说明: PXE Client:表示需要安装操作系统的机器,统称客户端: TFTP server:表示安装TFTPD服务的机器: DHCP server:表示安装DCHPD服务的机器: 在实际的 ...
- GitHub 上值得参考的完整的 iOS-App 源码
转自:https://www.zhihu.com/question/28518265 作者:wjh2005链接:https://www.zhihu.com/question/28518265/answ ...
- 设计模式GOF23(创建型模式)
• 创建型模式: 单例模式.工厂模式.抽象工厂模式.建造者模式.原型模式. • 结构型模式: –适配器模式.桥接模式.装饰模式.组合模式.外观模式.享元模式.代理模式. • 行为型模式: 模 ...
- Cookie俩步操作实现n天免登陆
实现这个功能主要思路是:在登录成功的时候去给用户名和密码加上Cookie,将他们的值存在Cookie中,为了下次登录记住用户名和密码,然后在登录界面,获取所有的cookie,然后将值一一遍历出来.和用 ...
- JavaScript基础5
字符串操作方法和属性 length 获取字符串的长度 str.chartAt(指定字符的索引) 获取指定位置的字符 返回string类型的值 str.concat(字符串) 链接多个字符串 ...