poj 3334 计算几何

有一个连通器,由两个漏斗组成,倒vol提及的水,问你连通器中水的高度是多少

解法:先求出水面可以到达的最低和最高的高度,然后二分答案判断

View Code
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const double eps = 1e-8;
const int maxn = 1010;
const double inf = 1000000000;
int n,m;
double vol,miny,maxy,ans;
struct Point{
    double x,y;
    Point(){};
    Point(double x,double y){
        this->x=x;
        this->y=y;
    }
    void read(){
        scanf("%lf%lf",&x,&y);
    }
}P[maxn],Q[maxn];
double min(double a,double b){
    return a<b?a:b;
}
int sign(double x){
    return (x>eps)-(x<-eps);
}
void input(){
    int i;
    miny=inf;
    scanf("%lf",&vol);
    scanf("%d",&n);
    for(i=0;i<n;i++) {
        P[i].read();
        if(sign(P[i].y-miny)<0)  miny=P[i].y;
    }
    scanf("%d",&m);
    for(i=0;i<m;i++){
        Q[i].read();
        if(sign(Q[i].y-miny)<0)  miny=Q[i].y;
    }
    maxy=min(min(P[0].y,P[n-1].y),min(Q[0].y,Q[m-1].y));
}
double getarea(Point *p,int n){
    int i;
    double area=0;
    for(i=0;i<n;i++) area+=p[(i+1)%n].y*(p[i].x-p[(i+2)%n].x);
    return fabs(area/2);
}
bool cross(Point a,Point b,double y){
    return sign(a.y-y)*sign(b.y-y)<=0;
}
Point intersect(Point p1,Point p2,Point p3,Point p4){
    Point p;
    double a1,b1,a2,b2,c1,c2,d;
    a1=p1.y-p2.y; b1=p2.x-p1.x; c1=p1.x*p2.y-p2.x*p1.y;
    a2=p3.y-p4.y; b2=p4.x-p3.x; c2=p3.x*p4.x-p4.x*p3.y;
    d=a1*b2-a2*b1;
    p.x=(-c1*b2+c2*b1)/d;
    p.y=(-a1*c2+a2*c1)/d;
    return p;
}
Point cut[maxn];
int tot;
double getvol(double y,int n,Point P[]){
    int i,j,k;
    tot=0;
    Point a=Point(0,y),b=Point(1,y);
    for(i=0;i<n-1;i++){
        if(cross(P[i],P[i+1],y)){
            cut[tot++]=intersect(P[i],P[i+1],a,b);
            break;
        }
    }
    for(j=i+1;j<n-1;j++){
        cut[tot++]=P[j];
        if(cross(P[j],P[j+1],y)){
            cut[tot++]=intersect(P[j],P[j+1],a,b);
            break;
        }
    }
    double area=getarea(cut,tot);
    return area;
}
double gao(double y){
    double a,b;
       a=getvol(y,n,P);
       b=getvol(y,m,Q);
       return a+b;
}
void solve(){
    double l=miny,r=maxy,mid;
    while(fabs(l-r)>eps){
        double mid=(l+r)/2;
        double test=gao(mid);
        int flag=sign(test-vol);
        if(flag<=0){
            ans=mid;
            l=mid;
        }
        else  r=mid;
    }
}
int main(){
    int t,i,j;
    scanf("%d",&t);
    while(t--){
        input();
        solve();
        printf("%.3lf\n",ans);
    }
    return  0;
}
posted @ 2012-04-21 17:26  Because Of You  Views(332)  Comments(0Edit  收藏  举报