计算几何 val.3

目录

  • 计算几何 val.3

    • 自适应辛普森法

      • 定积分
      • 引入
      • 辛普森公式
      • 处理精度
      • 代码实现
      • 模板
      • 时间复杂度
      • 练习
    • 闵可夫斯基和
    • Pick定理
      • 结论
      • 例题
    • 后记

计算几何 val.3

自适应辛普森法

可以用来求多边形的面积并(圆也行)

定积分

定积分的几何意义是函数的曲线上 \(x\) 的一段区间与 \(x\) 轴围成的曲边梯形的带符号面积

表示法为
\[
\int_{a}^{b} f(x) \mathrm{d} x
\]

引入

计算方法:

  1. 分成一堆小区间
    \[
    \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)
    \]
  2. 牛顿-莱布尼茨公式

    如果
    \[
    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|\)

    这也是连接定积分和不定积分的桥梁

对于一些难求的积分,我们可以用数值积分来求,其中常用的是自适应辛普森积分

辛普森公式

此公式用二次函数来拟合原函数
\[
\int_{a}^{b} f(x) \mathrm{d} x \approx \int_{a}^{b}\left(A x^{2}+B x+C\right) \mathrm{d} x
\]

\[
=\frac{A}{3}\left(b^{3}-a^{3}\right)+\frac{B}{2}\left(b^{2}-a^{2}\right)+C(b-a)
\]

\[
=\frac{2 A(b-a)\left(b^{2}+a b+a^{2}\right)+3 B(b+a)(b-a)+6 C(b-a)}{6}
\]

提出\(b-a\),
\[
=\frac{(b-a)\left(2 A b^{2}+2 A a b+2 A a^{2}+3 B b+3 B a+6 C\right)}{6}
\]

\[
=\frac{(b-a)\left(A a^{2}+B a+C+A b^{2}+B b+C+A a^{2}+2 A a b+A b^{2}+2 B b+2 B a+4 C\right)}{6}
\]

\[
=\frac{(b-a)\left(f(a)+f(b)+A(a+b)^{2}+2 B(a+b)+4 C\right)}{6}
\]

\[
=\frac{(b-a)\left(f(a)+f(b)+4\left(A\left(\frac{a+b}{2}\right)^{2}+B\left(\frac{a+b}{2}\right)+C\right)\right)}{6}
\]

\[
=\frac{(b-a)\left(f(a)+f(b)+4 f\left(\frac{a+b}{2}\right)\right)}{6}
\]

于是可以得到公式:
\[
\int_{a}^{b} f(x) \mathrm{d} x \approx \frac{(b-a)\left(f(a)+f(b)+4 f\left(\frac{a+b}{2}\right)\right)}{6}
\]
当然,对于二次函数这是对的

对于其余情况,\(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位都很稳

练习

找不到题啊。。

BZOJ2178

面积并:
\[
S=\int_l^rf(x)dx
\]
\(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了,最多写写做题记录

原文地址:https://www.cnblogs.com/lcyfrog/p/11712272.html

时间: 2024-12-29 10:11:12

计算几何 val.3的相关文章

计算几何 val.1

目录 计算几何 val.1 向量的点积 向量的叉积 一种奇怪的三角剖分求面积 凸包 点绕点旋转 后记 计算几何 val.1 本文并不是入门文章,供有高中数学基础的阅读 主要写一些重要的点和注意事项吧 向量的点积 如果两个向量同向(共线),那么它们的数量积为他们的模长之积. 如果两个向量夹角 \(<90^\circ\) ,那么它们的数量积为正. 如果两个向量夹角 \(=90^\circ\) ,那么他们的数量积为 \(0\) . 如果两个向量夹角 \(>90^\circ\) ,那么它们的数量积为负

计算几何 val.2

目录 计算几何 val.2 几何单位结构体板子 旋转卡壳 基础概念 求法 模板 半平面交 前置芝士:线段交 S&I算法 模板 最小圆覆盖 随机增量法 时间复杂度 模板 后记 计算几何 val.2 前置芝士:基础操作以及凸包 本文主要写旋转卡壳.半平面交.最小圆覆盖要注意的内容 几何单位结构体板子 不全(我知道 struct point{ double x,y; point(double x=0,double y=0): x(x),y(y){} //构造函数,非常方便 double operato

计算几何中的精度问题

转自:北岛知寒 计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模板一般就不成问题了.精度问题则不好说,有时候一个精度问题就可能成为一道题的瓶颈,简直"画龙点睛".这些年的题目基本是朝着越来越不卡精度的方向发展了,但是也不乏一些奇怪的题,另外有些常识不管题目卡不卡,都是应该知道的.今天我就开膛回顾下见过且还有印象的精度问题,由于本人见识和记忆均有限,望各位大神瞄过后不吝补充.另外,为了弥补我匮乏的文思,我可能乱扯些不太相关或者尽人皆知的东西凑数.那么,现在开始.

UESTC 1170 红与蓝 计算几何、贪心、红蓝点对

D - EN TARO Artanis Time Limit:1000MS     Memory Limit:65535KB     64bit IO Format:%lld & %llu Submit Status Practice UESTC 1170 Description 平面上有N个红点和N个蓝点,求红点到蓝点的最近距离 Input 第一行为一个整数N  接下来第N行每行两个整数xi,yi,表示第i个红点的坐标 接下来第N行每行两个整数xi,yi,表示第i个蓝点的坐标(1      

【bzoj1822】[JSOI2010]Frozen Nova 冷冻波 计算几何+二分+网络流最大流

题目描述 WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以瞬间杀灭一个小精灵. 在森林里有N个巫妖,每个巫妖释放Frozen Nova之后,都需要等待一段时间,才能再次施放.不同的巫妖有不同的等待时间和施法范围,但相同的是,每次施放都可以

【bzoj3630】[JLOI2014]镜面通道 对偶图+计算几何+网络流最小割

题目描述 在一个二维平面上,有一个镜面通道,由镜面AC,BD组成,AC,BD长度相等,且都平行于x轴,B位于(0,0).通道中有n个外表面为镜面的光学元件,光学元件α为圆形,光学元件β为矩形(这些元件可以与其他元件和通道有交集,具体看下图).光线可以在AB上任一点以任意角度射入通道,光线不会发生削弱.当出现元件与元件,元件和通道刚好接触的情况视为光线无法透过(比如两圆相切).现在给出通道中所有元件的信息(α元件包括圆心坐标和半径xi,yi,ri,β元件包括左下角和右上角坐标x1,y1,x2,y2

计算几何——精度问题

计算几何中的精度问题(转)(谢谢原创) 计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模板 一般就不成问题了.精度问题则不好说,有时候一个精度问题就可能成为一道题的瓶颈,简直“画龙点睛”.这些年的题目基本是朝着越来越不卡精度的方向发展 了,但是也不乏一些%^&%题#$%$^,另外有些常识不管题目卡不卡,都是应该知道的.今天我就开膛回顾下见过且还有印象的精度问题,由于本人 见识和记忆均有限,望各位大神瞄过后不吝补充.另外,为了弥补我匮乏的文思,我可能乱扯些不太相关或者尽人

计算几何精度问题(转)

计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模板一般就不成问题了.精度问题则不好说,有时候一个精度问题就可能成为一道题的瓶颈,简直“画龙点睛”.这些年的题目基本是朝着越来越不卡精度的方向发展了,但是也不乏一些%^&%题#$%$^,另外有些常识不管题目卡不卡,都是应该知道的.今天我就开膛回顾下见过且还有印象的精度问题,由于本人见识和记忆均有限,望各位大神瞄过后不吝补充.另外,为了弥补我匮乏的文思,我可能乱扯些不太相关或者尽人皆知的东西凑数.那么,现在开始. 计算几何的精

计算几何中的精度问题(转)

计算几何头疼的地方一般在于代码量大和精度问题,代码量问题只要平时注意积累模板一般就不成问题了.精度问题则不好说,有时候一个精度问题就可能成为一道题的瓶颈,简直“画龙点睛”.这些年的题目基本是朝着越来越不卡精度的方向发展了,但是也不乏一些%^&%题#$%$^,另外有些常识不管题目卡不卡,都是应该知道的.今天我就开膛回顾下见过且还有印象的精度问题,由于本人见识和记忆均有限,望各位大神瞄过后不吝补充.另外,为了弥补我匮乏的文思,我可能乱扯些不太相关或者尽人皆知的东西凑数.那么,现在开始. 计算几何的精