有一個連通器,由兩個漏鬥組成,倒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;}