EOJ-1708//POJ3334
题意:
有一个连通器,由两个漏斗组成(关于漏斗的描述见描述)。
现向漏斗中注入一定量的水,问最终水的绝对位置(即y轴坐标)
思路:
总体来说分为3种情况。
1.两个漏斗可能同时装有水。
2.只可能a漏斗有水。
3.只可能b漏斗有水。
于是可以二分枚举y的坐标。
关键在于对于某个y坐标来说,要求出新的交点,再求面积。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }
keep moving...