首页 > 代码库 > EOJ-1708//POJ3334

EOJ-1708//POJ3334

题意:

  有一个连通器,由两个漏斗组成(关于漏斗的描述见描述)。

  现向漏斗中注入一定量的水,问最终水的绝对位置(即y轴坐标)

思路:

  总体来说分为3种情况。

  1.两个漏斗可能同时装有水。

  2.只可能a漏斗有水。

  3.只可能b漏斗有水。

  于是可以二分枚举y的坐标。

  关键在于对于某个y坐标来说,要求出新的交点,再求面积。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <stdlib.h>
  4 #include <math.h>
  5 #include <algorithm>
  6 #include <iostream>
  7 using namespace std;
  8 
  9 const int maxn = 1005;
 10 const double eps = 1e-8;
 11 const double inf = 999999999.99;
 12 
 13 struct Point{
 14     double x,y;
 15 }a[ maxn ],b[ maxn ],res[ maxn ],amid,bmid;
 16 
 17 double xmult( Point a,Point b,Point c ){
 18     double ans = (a.x-c.x)*(b.y-c.y) - (a.y-c.y)*(b.x-c.x);
 19     return ans;
 20 }
 21 
 22 int cmp( Point a,Point b ){
 23     if( a.x!=b.x ) return a.x<b.x;
 24     else return a.y>b.y;
 25 }
 26 
 27 double area( Point pnt[],int n ){
 28     double ans = 0;
 29     for( int i=1;i<n-1;i++ ){
 30         ans += xmult( pnt[0],pnt[i],pnt[i+1] );
 31     }
 32     return fabs( 0.5*ans );
 33 }
 34 
 35 int main(){
 36     //freopen("out.txt","w",stdout);
 37     int T;
 38     scanf("%d",&T);
 39     while( T-- ){
 40         double aim;
 41         double ansY = 0;
 42         scanf("%lf",&aim);
 43         int n1,n2;
 44         scanf("%d",&n1);
 45         double ymax = inf;
 46         int flag1 = -1;
 47         for( int i=0;i<n1;i++ ){
 48             scanf("%lf%lf",&a[i].x,&a[i].y);
 49             if( ymax>a[i].y ){
 50                 ymax = a[i].y;
 51                 flag1 = i;
 52             }
 53         }
 54         amid = a[ flag1 ];
 55         scanf("%d",&n2);
 56         ymax = inf;
 57         int flag2 = -1;
 58         for( int i=0;i<n2;i++ ){
 59             scanf("%lf%lf",&b[i].x,&b[i].y);
 60             if( ymax>b[i].y ){
 61                 ymax = b[i].y;
 62                 flag2 = i;
 63             }
 64         }
 65         bmid = b[ flag2 ];
 66         //input
 67         double aYmin = min( a[0].y,a[n1-1].y );
 68         double bYmin = min( b[0].y,b[n2-1].y );
 69         //printf("aYmin = %lf bYmin = %lf\n",aYmin,bYmin);
 70         double abYmax = max( aYmin,bYmin );
 71         double abYmin = min( amid.y,bmid.y );
 72         double L ,R ;
 73         //printf("L = %lf , R = %lf \n",L,R);
 74         int special = -1;
 75         if( aYmin<=bmid.y )//a is lower
 76         {
 77             special = 1;
 78         }
 79         else if( bYmin<=amid.y )
 80         {
 81             special = 2;
 82         }
 83         if( special==-1 ){        
 84             L = abYmin;
 85             R = min( aYmin,bYmin );
 86             while( L<R ){
 87                 double mid = (L+R)/2.0;
 88                 double sumArea = 0;
 89                 /*******solve b******/
 90                 //printf("mid = %lf\n",mid);
 91                 if( mid>bYmin ){
 92                     int cnt = 0;
 93                     double newY = bYmin;
 94                     int f = -1;
 95                     for( int i=0;i<n2;i++ ){
 96                         if( b[i].y<=newY ){
 97                             res[ cnt++] = b[ i ];
 98                             f = i;
 99                         }
100                         else break;
101                     }
102                     if( f==-1 ){}
103                     else{
104                         Point tmp;
105                         tmp.y = newY;
106                         tmp.x = (b[ f+1 ].x-b[ f ].x)*(newY-b[f].y)/(b[f+1].y-b[f].y) + b[f].x;
107                         res[ cnt++ ] = tmp;
108                     }
109                     sumArea += area( res,cnt );
110                 }
111                 else if( mid<=bmid.y ){}
112                 else{
113                     //printf("here\n");
114                     int cnt = 0;
115                     int f = -1;
116                     for( int i=0;i<n2;i++ ){
117                         if( b[i].y<=mid ){
118                             f = i;
119                             break;
120                         }
121                     }
122                     //printf("f = %d\n",f);
123                     Point tmp;
124                     tmp.y = mid;
125                     tmp.x = b[f].x-( (b[f].x-b[f-1].x)*(mid-b[f].y)/(b[f-1].y-b[f].y) );
126                     res[ cnt++] = tmp;
127                     for( int i=f;i<n2;i++ ){
128                         if( b[i].y<mid ){
129                             res[ cnt++ ] = b[i];
130                             f = i;
131                         }
132                         else break;
133                     }
134                     tmp.y = mid;
135                     tmp.x = (b[ f+1 ].x-b[ f ].x)*(mid-b[f].y)/(b[f+1].y-b[f].y) + b[f].x;
136                     res[ cnt++ ] = tmp;
137                     //printf("cnt = %d\n",cnt);
138                     sumArea += area( res,cnt );
139                 } 
140                 //printf("sumarea = %lf \n",sumArea);
141             /********solve a *****/
142                 if( mid>aYmin ){
143                     int cnt = 0;
144                     double newY = aYmin;
145                     int f = -1;
146                     for( int i=0;i<n1;i++ ){
147                         if( a[i].y<=newY ){
148                             res[ cnt++] = a[ i ];
149                             f = i;
150                         }
151                         else break;
152                     }
153                     if( f==-1 ){}
154                     else{
155                         Point tmp;
156                         tmp.y = newY;
157                         tmp.x = (a[ f+1 ].x-a[ f ].x)*(newY-a[f].y)/(a[f+1].y-a[f].y) + a[f].x;
158                         res[ cnt++ ] = tmp;
159                     }
160                     sumArea += area( res,cnt );
161                 }
162                 else if( mid<=amid.y ){}
163                 else{
164                     int cnt = 0;
165                     int f = -1;
166                     for( int i=0;i<n1;i++ ){
167                         if( a[i].y<=mid ){
168                             f = i;
169                             break;
170                         }
171                     }
172                     Point tmp;
173                     tmp.y = mid;
174                     tmp.x = a[f].x-( (a[f].x-a[f-1].x)*(mid-a[f].y)/(a[f-1].y-a[f].y) );
175                     res[ cnt++] = tmp;
176                     for( int i=f;i<n1;i++ ){
177                         if( a[i].y<mid ){
178                             res[ cnt++ ] = a[i];
179                             f = i;
180                         }
181                         else break;
182                     }
183                     tmp.y = mid;
184                     tmp.x = (a[ f+1 ].x-a[ f ].x)*(mid-a[f].y)/(a[f+1].y-a[f].y) + a[f].x;
185                     res[ cnt++ ] = tmp;
186                     sumArea += area( res,cnt );
187                 }
188                 //printf("sumarea2 = %lf\n\n\n",sumArea);
189                 if( fabs(sumArea-aim)<=eps ){
190                     ansY = mid;
191                     break;
192                 }
193                 else if( sumArea>aim ){
194                     R = mid-eps;
195                 }
196                 else {
197                     L = mid+eps;
198                     ansY = mid;    
199                 }
200             }
201         }//ab可能都同时都有水 
202         else{
203             //printf("special = %d\n",special);
204             double sumArea = 0;
205             if( special==1 ){//‘1’表示只有a会有水 
206                 double L = amid.y;
207                 double R = aYmin;
208                 while( L<R ){
209                     double mid = (L+R)/2.0;
210                     //printf("mid = %lf\n",mid);
211                     int cnt = 0;
212                     int f = -1;
213                     for( int i=0;i<n1;i++ ){
214                         if( a[i].y<=mid ){
215                             f = i;
216                             break;
217                         }
218                     }
219                     Point tmp;
220                     tmp.y = mid;
221                     tmp.x = a[f].x-( (a[f].x-a[f-1].x)*(mid-a[f].y)/(a[f-1].y-a[f].y) );
222                     res[ cnt++] = tmp;
223                     for( int i=f;i<n1;i++ ){
224                         if( a[i].y<mid ){
225                             res[ cnt++ ] = a[i];
226                             f = i;
227                         }
228                         else break;
229                     }
230                     tmp.y = mid;
231                     tmp.x = (a[ f+1 ].x-a[ f ].x)*(mid-a[f].y)/(a[f+1].y-a[f].y) + a[f].x;
232                     res[ cnt++ ] = tmp;
233                     sumArea += area( res,cnt );
234                     //printf("cnt = %d\n",cnt);
235                     //printf("sumarea = %lf\n",sumArea);
236                     if( fabs(sumArea-aim)<=eps ){
237                         ansY = mid;
238                         break;
239                     }
240                     else if( sumArea>aim ) {
241                         R = mid-eps;
242                     }
243                     else {
244                         L = mid + eps;
245                         ansY = L;
246                     }
247                 }
248             }    
249             else{//‘2‘表示只有b会有水 
250                 double L = bmid.y;
251                 double R = bYmin;
252                 //printf("L = %lf,R = %lf\n",L,R);
253                 while( L<R ){
254                     double mid = (L+R)/2.0;
255                     //printf("mid = %lf\n",mid);
256                     int cnt = 0;
257                     int f = -1;
258                     for( int i=0;i<n2;i++ ){
259                         if( b[i].y<=mid ){
260                             f = i;
261                             break;
262                         }
263                     }
264                     Point tmp;
265                     tmp.y = mid;
266                     tmp.x = b[f].x-( (b[f].x-b[f-1].x)*(mid-b[f].y)/(b[f-1].y-b[f].y) );
267                     res[ cnt++] = tmp;
268                     for( int i=f;i<n2;i++ ){
269                         if( b[i].y<mid ){
270                             res[ cnt++ ] = b[i];
271                             f = i;
272                         //printf("add : i = %d\n",i);
273                         }
274                         else break;
275                     }
276                     tmp.y = mid;
277                     tmp.x = (b[ f+1 ].x-b[ f ].x)*(mid-b[f].y)/(b[f+1].y-b[f].y) + b[f].x;
278                     res[ cnt++ ] = tmp;
279                     //printf("cnt = %d\n",cnt);
280                     sumArea += area( res,cnt );
281                     if( fabs(sumArea-aim)<=eps ){
282                         ansY = mid;
283                         break;
284                     }
285                     else if( sumArea>aim ) {
286                         R = mid-eps;
287                     }
288                     else {
289                         L = mid + eps;
290                         ansY = L;
291                     }
292                 }
293             }
294         } 
295         printf("%.3lf\n",ansY);
296     }
297     return 0;
298 }
View Code