ZOJ 3913
题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5640
题意:
往一个立方体容器里面注水。长宽已知,高不可观。
矩阵容器里面有一些不想交的球体和立方体,大小什么的都给出来。
现要注水v升,求水平面相对于立方体容器高度。
思路:
难点在推球体积分公式啊。
其实高数学好就不会有问题,假设水平面和球体是相交的,积分符号为S,那么算出水平面和球体的距离d,则temp = S(PI*(r*r-d*d)),判断一下水平面在球体中心上还是下加个常数就可以。
当然二分的上下界写错会使劲WA这种事我是不会写的。
源码:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 100000 + 5;
const double PI = 3.1415926535897932384626433832795;
const double eps = 1e-6;
struct D
{
double h, a, b, c;
}d[MAXN];
struct C
{
double h, r;
}l[MAXN];
int main()
{
// freopen("K.in", "r", stdin);
// freopen("ZOJ 3913 WA.out", "w", stdout);
int t;
scanf("%d", &t);
while(t--){
double w, s, v;
int n, m;
// double sum = 0;
double sv = 0;
scanf("%lf%lf%lf%d%d", &w, &s, &v, &n, &m);
for(int i = 0 ; i < n ; i++){
scanf("%lf%lf%lf%lf", &d[i].h, &d[i].a, &d[i].b, &d[i].c);
sv += d[i].a * d[i].b * d[i].c;
}
for(int i = 0 ; i < m ; i++){
scanf("%lf%lf", &l[i].h, &l[i].r);
sv += PI * l[i].r * l[i].r * l[i].r * 4.0 / 3.0;
}
// sv = sum;
double le = v / (w * s), re = (v + sv) / (w * s);
while(fabs(re - le) > eps){
double mid = (re + le) / 2.0;
// printf("re = %f, le = %f, mid = %f\n", re, le, mid);
double sum = 0;
for(int i = 0 ; i < n ; i++){
if((mid <= d[i].h + d[i].c / 2.0) && (mid >= d[i].h - d[i].c / 2.0)){
sum += (mid - d[i].h + d[i].c / 2.0) * d[i].a * d[i].b;
// printf("factor = %f\n", (mid - d[i].h + d[i].c / 2) * d[i].a * d[i].b);
}
else if(mid > d[i].h + d[i].c / 2.0)
sum += d[i].a * d[i].b * d[i].c;
}
for(int i = 0 ; i < m ; i++){
if((mid <= l[i].h + l[i].r) && (mid >= l[i].h - l[i].r)){
double u = l[i].h - mid;
if(u < 0) u = -u;
double temp = PI*(l[i].r*l[i].r*u-u*u*u/3.0);
if(mid > l[i].h) temp = temp + 2.0 * PI * l[i].r * l[i].r * l[i].r / 3.0;
else temp = 2.0 * PI * l[i].r * l[i].r * l[i].r / 3.0 - temp;
// printf("temp = %f\n", temp);
sum += temp;
// double u = mid - (l[i].h - l[i].r);
// sum += PI * (l[i].r * u * u - u * u * u / 3.0);
}
else if(mid > l[i].h + l[i].r){
sum += l[i].r * l[i].r * l[i].r * PI * 4.0 / 3.0;
}
}
sum = w * s * mid - sum;
// printf("sum = %.10f\n", sum);
if(sum >= v - eps){
re = mid;
}
else
le = mid;
}
printf("%.6f\n", re);
}
return 0;
}