AOJ1313 Intersection of Two Prisms(自适应辛普森积分)

AOJ1313 Intersection of Two Prisms(自适应辛普森积分)

题目链接:传送门
思路:

SImpson积分了解:传送门

我们可以将x轴分割为数个小区间的形式,然后对每个小区间进行计算相交的体积,然后将结果相加即可,对于棱平行于z轴的棱柱P1,在 [ x , x + d x ] [x,x+dx] [x,x+dx]处分割的长方体为 x ′ ∈ [ x , x + d x ] , y ′ ∈ [ y 1 , y 2 ] , z ′ ∈ [ − ∞ , + ∞ ] x'\in[x,x+dx],y'\in[y1,y2],z'\in [-\infty,+\infty] x[x,x+dx],y[y1,y2],z[,+] 。对于棱柱P2,在x处分割的长方体为 x ′ ∈ [ x , x + d x ] , y ′ ∈ [ − ∞ , + ∞ ] , z ′ ∈ [ z 1 , z 2 ] x'\in[x,x+dx],y'\in [-\infty,+\infty],z'\in[z1,z2] x[x,x+dx],y[,+],z[z1,z2]。所以相交的体积为 d x ∗ ( z 2 − z 1 ) ∗ ( y 2 − y 1 ) dx*(z2-z1)*(y2-y1) dx(z2z1)(y2y1).

因为多边形在x处的截距的长度随着x的增加在顶点处不连续,即不可导,所以不能一次全部定积分。

但我们可以分段统计,对于区间 [ x 1 , x 2 ] ​ [x1,x2]​ [x1,x2] 如果在两个多边形中都不存在断点,即区间 [ x 1 , x 2 ] ​ [x1,x2]​ [x1,x2]分别是两多边形的某条边的x的范围,我们就可以定积分求出他们的积分。

这个很简单,我们只需把两个多边形的顶点的X全部存起来,从小到大排序,那么挨着的两个X代表的区间绝对是连续的,可以看出P1的底面在x处的截距y是关于x的线性函数,所以他们的乘积 f ( x ) = ( z 2 − z 1 ) ∗ ( y 2 − y 1 ) ​ f(x)=(z2-z1)*(y2-y1)​ f(x)=(z2z1)(y2y1)是个二次函数,所以 ∫ x 1 x 2 f ( x ) ∗ d x ​ \int _{x1}^{x2} f(x)*dx​ x1x2f(x)dx 可以用Simpson积分计算。

代码:

#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=550;
const int inf=0x3f3f3f3f;
int _m,_n;//第一个是m多边形,第二个是n多边形
int X1[105],Y1[105],X2[105],Z2[105];//下标从0开始
double width(int X[],int Y[],int n,double x)//对于n个点的多边形(x,y)
{
    double down=1e8,up=-1e8;
    for(int i=0;i<n;++i)
    {
        int x1=X[i],y1=Y[i],x2=X[(i+1)%n],y2=Y[(i+1)%n];
        if(x1>x2){
            swap(x1,x2);swap(y1,y2);
        }
        if(x>=x1&&x<=x2){
            double y=y1+(x-x1)*(y2*1.0-y1)/(x2-x1);
            down=min(down,y);
            up=max(up,y);
        }
    }
    return max(0.0,up-down);
}
double f(double x)
{
    return width(X1,Y1,_m,x)*width(X2,Z2,_n,x);
}
double simpson(double a,double b)//要求a<b
{
    double c=(a+b)/2.0;
    return (b-a)/6.0*(f(a)+4*f(c)+f(b));
}
vector<int> sx;
int main()
{
    ios::sync_with_stdio(false);cin.tie(0);
    while(cin>>_m>>_n)
    {
        if(_m==0&&_n==0) return 0;
        sx.clear();
        for(int i=0;i<_m;++i){
            cin>>X1[i]>>Y1[i];
            sx.push_back(X1[i]);
        }
        for(int i=0;i<_n;++i){
            cin>>X2[i]>>Z2[i];
            sx.push_back(X2[i]);
        }
        sort(sx.begin(),sx.end());
        int min1=*min_element(X1,X1+_m),max1=*max_element(X1,X1+_m);
        int min2=*min_element(X2,X2+_n),max2=*max_element(X2,X2+_n);
        double res=0;
        for(int i=0;i+1<sx.size();++i)
        {
            int a=sx[i],b=sx[i+1];
            if(a>=min1&&a<=max1&&a>=min2&&a<=max2&&b>=min1&&b<=max1&&b>=min2&&b<=max2)
            {
                res+=simpson(a*1.0,b*1.0);
            }
        }
        cout<<fixed<<setprecision(10)<<res<<endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的公寓报修管理系统,源码+数据库+毕业论文+视频演示 现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集中处理数据信息的管理方式。本公寓报修管理系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此公寓报修管理系统利用当下成熟完善的Spring Boot框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。公寓报修管理系统有管理员,住户,维修人员。管理员可以管理住户信息和维修人员信息,可以审核维修人员的请假信息,住户可以申请维修,可以对维修结果评价,维修人员负责住户提交的维修信息,也可以请假。公寓报修管理系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。 关键词:公寓报修管理系统;Spring Boot框架;MySQL;自动化;VUE
毕业设计,基于SpringBoot+Vue+MySQL开发的社区医院管理系统,源码+数据库+毕业论文+视频演示 信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的社区医院管理系统实现了病例信息、字典表、家庭医生、健康档案、就诊信息、前台、药品、用户、用户、用户表等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让社区医院管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。 关键字:社区医院管理系统;信息管理,时效性,安全性,MySql
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值