Intersection of Two Prisms Aizu - 1313 (Simpson积分)

传送门

题意:有一个侧棱与z轴平行的棱柱P1和一个侧棱与y轴平行的棱柱P2.它们都向两端无限延伸,底面分别是包含M个顶点和N个顶点的凸多边形,其中第i个顶点的坐标分别是(X1i,Y1i)和(X2i,Z2i)。请计算这两个棱柱公共部分的体积。

题解:使用Simpson积分做

附上代码:


#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>

using namespace std;

const int MAX_N=150;
const double INF=99999;

int M,N;
int X1[MAX_N],Y1[MAX_N];
int X2[MAX_N],Z2[MAX_N];

double width(int *X,int *Y,int n,double x)
{
    double lb=INF,ub=-INF;
    for(int i=0;i<n;i++){
        double x1=X[i],y1=Y[i],x2=X[(i+1)%n],y2=Y[(i+1)%n];
        if((x1-x)*(x2-x)<=0&&x1!=x2){
            double y=y1+(y2-y1)*(x-x1)/(x2-x1);
            lb=min(lb,y);
            ub=max(ub,y);
        }
    }
    return max(0.0,ub-lb);
}

void solve()
{
    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);
    vector<int>xs;
    for(int i=0;i<M;i++){
        xs.push_back(X1[i]);
    }
    for(int i=0;i<N;i++){
        xs.push_back(X2[i]);
    }
    sort(xs.begin(),xs.end());
    double res=0;
    for(int i=0;i+1<xs.size();i++){
        double a=xs[i],b=xs[i+1],c=(a+b)/2;
        if(min1<=c&&c<=max1&&min2<=c&&c<=max2){
            double fa=width(X1,Y1,M,a)*width(X2,Z2,N,a);
            double fb=width(X1,Y1,M,b)*width(X2,Z2,N,b);
            double fc=width(X1,Y1,M,c)*width(X2,Z2,N,c);
            res+=(b-a)/6*(fa+4*fc+fb);
        }
    }
    printf("%.10f\n",res);
}

int main()
{
    while(scanf("%d%d",&M,&N)!=EOF){
        if(M==0&&N==0){
            break;
        }
        for(int i=0;i<M;i++){
            scanf("%d%d",&X1[i],&Y1[i]);
        }
        for(int i=0;i<N;i++){
            scanf("%d%d",&X2[i],&Z2[i]);
        }
        solve();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/83096793