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

 

你可能感兴趣的:(poj)