Codeforces Gym 100286A. Aerodynamics 计算几何 求二维凸包面积

Problem A. Aerodynamics
Time Limit: 20 Sec

Memory Limit: 256 MB

题目连接

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=86821#problem/A

Description

Bill is working in a secret laboratory. He is developing missiles for national security projects. Bill is the head of the aerodynamics department. One surprising fact of aerodynamics is called Whitcomb area rule. An object flying at high-subsonic speeds develops local supersonic airflows and the resulting shock waves create the effect called wave drag. Wave drag does not depend on the exact form of the object, but rather on its cross-sectional profile.
Consider a coordinate system with OZ axis pointing in the direction of object’s motion. Denote the area of a section of the object by a plane z = z0 as S(z0). Cross-sectional profile of the object is a function S that maps z0 to S(z0). There is a perfect aerodynamic shape called Sears-Haack body. The closer cross-sectional profile of an object to the cross-sectional profile of Sears-Haack body, the less wave drag it introduces. That is an essence of Whitcomb area rule.
Bill’s department makes a lot of computer simulations to study missile’s aerodynamic properties before it is even built. To approximate missile’s cross-sectional profile one takes samples of S(z0) for integer arguments z0 from zmin to zmax.

Your task is to find the area S(z0) for each integer z0 from zmin to zmax, inclusive, given the description of the missile. The description of the missile is given to you as a set of points. The missile is the minimal convex solid containing all the given points. It is guaranteed that there are four points that do not belong to the same plane.

Input

The first line of the input file contains three integer numbers: n, zmin and zmax (4 ≤ n ≤ 100, 0 ≤ zmin ≤ zmax ≤ 100). The following n lines contain three integer numbers each: x, y, and z coordinates of the given points. All coordinates do not exceed 100 by their absolute values. No two points coincide. There are four points that do not belong to the same plane.

Output

For each integer z0 from zmin to zmax, inclusive, output one floating point number: the area S(z0). The area must be precise to at least 5 digits after decimal point.

Sample Input

9 0 5
0 0 5
-3 0 2
0 -1 2
3 0 2
0 1 2
2 2 0
2 -2 0
-2 -2 0
-2 2 0

Sample Output

16.00000
14.92000
10.08000
4.48000
1.12000
0.00000

HINT

 

题意

给你一个由n个点构成的三维凸包,让你输出从zmin到zmax的所有截面的面积

题解

对于每一个截面,我们n^2暴力出在这个截面上的所有点,然后直接套版求这个凸包的面积就好了

代码:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define test freopen("test.txt","r",stdin)
#define maxn 100010
#define mod 1000000007
#define eps 1e-9
const int inf=0x3f3f3f3f;
const ll infll = 0x3f3f3f3f3f3f3f3fLL;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
//**************************************************************************************

struct node
{
    double x,y,z;
};
bool cmp(node a,node b)
{
    return a.z<b.z;
}
struct POINT
{
 double x;
 double y;
 POINT(double a=0, double b=0) { x=a; y=b;} //constructor

};
POINT operator - (POINT A,POINT B){return POINT(A.x-B.x,A.y-B.y);}
bool cmp1(POINT a,POINT b)
{
    if(fabs(a.x-b.x)<eps)
        return a.y<b.y;
    return a.x<b.x;
}
node a[110];
node c[100000];
int tot=0;
POINT kiss[100000];
double Cross(POINT a,POINT b)
{
    return a.x*b.y-a.y*b.x;
}
int CH(POINT* p,int n,POINT* ch)
{
    sort(p,p+n,cmp1);
    int m=0;
    for(int i=0;i<n;i++)
    {
        while(m>1&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    int k=m;
    for(int i=n-2;i>=0;i--)
    {
        while(m>k&&Cross(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;
        ch[m++]=p[i];
    }
    if(n>1)m--;
    return m;
}
double area_of_polygon(int vcount,POINT polygon[])
{
     int i;
     double s;
     if(vcount<3)
        return 0;
     s=polygon[0].y*(polygon[vcount-1].x-polygon[1].x);
     for (i=1;i<vcount;i++)
        s+=polygon[i].y*(polygon[(i-1)].x-polygon[(i+1)%vcount].x);
     return s/2;
}
vector<node>Q1;
vector<node>Q2;
POINT ki[10010];
int main()
{
    freopen("aerodynamics.in","r",stdin);
    freopen("aerodynamics.out","w",stdout);
    int n=read(),zmin=read(),zmax=read();
    for(int i=0;i<n;i++)
        cin>>a[i].x>>a[i].y>>a[i].z;
    sort(a,a+n,cmp);
    int j=0;
    for(int i=zmin;i<=zmax;i++)
    {
        Q1.clear();
        Q2.clear();
        memset(kiss,0,sizeof(kiss));
        memset(ki,0,sizeof(ki));
        tot=0;
        double ii=i*1.0;
        while((a[j].z-ii)<-eps&&j<n)
            j++;
        for(int k=0;k<n;k++)
        {
            if(a[k].z<i)
                Q1.push_back((node){a[k].x,a[k].y,a[k].z});
            else if(a[k].z>i)
                Q2.push_back((node){a[k].x,a[k].y,a[k].z});
            else
                kiss[tot].x=a[k].x,kiss[tot++].y=a[k].y;
        }
        for(int k=0;k<Q1.size();k++)
        {
            for(int t=0;t<Q2.size();t++)
            {
                kiss[tot].x=(Q2[t].x-Q1[k].x)*(ii-Q1[k].z)/(Q2[t].z-Q1[k].z)+Q1[k].x;
                kiss[tot++].y=(Q2[t].y-Q1[k].y)*(ii-a[k].z)/(Q2[t].z-Q1[k].z)+Q1[k].y;
            }
        }

        /*
        if(i==4)
        {
            cout<<"--------------------------"<<endl;
            for(int kk=0;kk<j;kk++)
                cout<<a[kk].x<<" "<<a[kk].y<<" "<<a[kk].z<<endl;
            cout<<"--------------------------"<<endl;
            for(int kk=j;kk<n;kk++)
                cout<<a[kk].x<<" "<<a[kk].y<<" "<<a[kk].z<<endl;
            cout<<"--------------------------"<<endl;
            for(int kk=0;kk<tot;kk++)
                cout<<kiss[kk].x<<" "<<kiss[kk].y<<endl;
            cout<<"--------------------------"<<endl;
        }
        */
        int ttt=CH(kiss,tot,ki);
        printf("%.5lf\n",area_of_polygon(ttt,ki));
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值