Aquarium Tank(csu1634+几何+二分)Contest2087 - 湖南多校对抗赛(2015.05.24)-G

 Aquarium Tank

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 15  Solved: 4
[Submit][Status][Web Board]

Description

You just bought an “artistic” aquarium tank that has an interesting shape, and you poured L litres of water into the tank. How high is the water in the tank?
When you look at this tank from one side, it has the shape of a convex polygon. This polygon has exactly two vertices on the table (y-coordinates are 0), and all other vertices have positive y-coordinates. There are also exactly two vertices with maximum y-coordinates, and water is poured into the opening between these two vertices. This aquarium tank has a depth of D centimetres. The tank is glued to the table, so no matter what shape it has, it keeps its position and does not tip over. All coordinates and lengths in this problem are given in centimetres. It should be noted that each cubic metre is equivalent to 1 000 litres.
An illustration showing the configuration of the tank of the first sample input is given below:

Input

The input consists of a single test case. The first line contains an integer N (4 ≤ N ≤ 100) giving the number of vertices in the polygon. he next line contains two integers D and L, where 1 ≤ D ≤ 1000 is he depth of the aquarium tank and 0 L 2 000 is the number of litres f water to pour into the tank. The next N lines each contains two integers, giving the (x, y) coordinates of the vertices of the convex polygon in counterclockwise order. The absolute values of x and y are at most 1 000. You may assume that the tank has a positive capacity, and you never pour more water than the tank can hold.

 

Output

Print the height of the water (in centimetres) in the aquarium tank on a line to 2 decimal places.

 

Sample Input

4
30 50
20 0
100 0
100 40
20 40

Sample Output

20.83

HINT

 

Source



 

题意:有一个横放是多边形的棱柱。问L升水,注入其中,容器的深度是多少。

思路:棱柱的体积等于底面积成高,so、、、我可以二分多边形的高度(用平行与X轴的直线求切割多边形)取下半部分是面积;

坑!比赛的时候,我以为第一组边一定是在x轴上的。。。o(︶︿︶)o 唉,结果是一定有一组边在x轴上,但不一定是第一组!。。。

 

转载请注明出处:寻找&星空の孩子 

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1634

#include<cstdio>
#include<cmath>
#include<iostream>
#define PI acos(-1.0)
using namespace std;
 
struct Point
{
    double x,y;
    Point(double x=0,double y=0):x(x),y(y) {}
 
};
 
double hmax;
double D,L;
 
typedef Point Vector;
 
Vector operator + (Vector A,Vector B)
{
    return Vector(A.x+B.x,A.y+B.y);
}
 
Vector operator - (Point A,Point B)
{
    return Vector(A.x-B.x,A.y-B.y);
}
 
Vector operator * (Vector A,double p)
{
    return Vector(A.x*p,A.y*p);
}
 
Vector operator / (Vector A,double p)
{
    return Vector(A.x/p,A.y/p);
}
 
bool operator < (const Point& a,const Point& b)
{
    return a.x<b.x||(a.x==b.x && a.y<b.y);
}
 
const double eps = 1e-8;
 
int dcmp(double x)
{
    if(fabs(x)<eps)return 0;
    else return x < 0 ? -1 : 1;
}
bool operator == (const Point& a,const Point& b)
{
    return dcmp(a.x-b.x)==0 && dcmp(a.y-b.y)==0;
}
 
double Dot(Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}
double length(Vector A)
{
    return sqrt(Dot(A,A));
}
double Angle(Vector A,Vector B)
{
    return acos(Dot(A,B)/length(A)/length(B));
}
 
double Cross(Vector A,Vector B)
{
    return A.x*B.y-B.x*A.y;
}
double Area2(Point A,Point B,Point C)
{
    return Cross(B-A,C-A);
}
 
double PArea(Point *p,int n)
{
    double area=0;
    for(int i=0; i<n; i++)
    {
        area+=Cross(p[i],p[(i+1)%n]);
    }
    return fabs(area/2);
}
 
Point GetLineIntersection(Point P,Vector v,Point Q,Vector w)
{
    Vector u=P-Q;
    return P+v*Cross(w,u)/Cross(v,w);
}
Point read_point(Point &P)
{
    scanf("%lf%lf",&P.x,&P.y);
    hmax=max(hmax,P.y);
    return P;
}
Point get_point(Point a, Point b, double y0)
{
    if(fabs(a.x - b.x) < eps) return Point(a.x, y0);
    double bi = (y0 - a.y) / (b.y - a.y);
    return Point(a.x + bi * (b.x - a.x), a.y + bi * (b.y - a.y));
}
int main()
{
    Point po[105],Q[105];
    int T,n,q,i;
    while(scanf("%d",&n)!=EOF)
    {
        scanf("%lf%lf",&D,&L);
        hmax=0;
        for(i=0; i<n; i++)
        {
            read_point(po[i]);
        }
        double d=0,h=hmax;
        while(h-d>eps)
        {
            q=0;
            int per=n-1;
            double m=(d+h)/2;
            Point M(0,m);
            Vector w(1,0);
            for(int i=0; i<n; i++)
            {
                if((m-po[i].y)*(m-po[per].y)<eps)
                {
                    Vector PP=po[i]-po[per];
                    Q[q++]=GetLineIntersection(po[per],PP,M,w);
                    //   Q[q++]=get_point(po[i],po[per],m);
                }
                if((m-po[i].y)>eps)
                {
                    Q[q++]=po[i];
                }
                per=i;
            }
            double area=PArea(Q,q);
            if(L*1000-area*D>eps) d=m;
            else h=m;
        }
        printf("%.2f\n",d);
    }
    return 0;
}
 
/**************************************************************
    Problem: 1634
    User: aking2015
    Language: C++
    Result: Accepted
    Time:0 ms
    Memory:1500 kb
****************************************************************/


 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值