您的位置:首页 > 其它

2015final题 Cutting Cheese 二分切点+积分

2015-06-03 17:09 411 查看
题目链接:https://icpc.kattis.com/problems/cheese

Of course you have all heard of the International Cheese Processing Company. Their machine for cutting a piece of cheese into slices of exactly the same thickness is a classic. Recently they produced a machine able to cut a spherical cheese (such as Edam) into
slices – no, not all of the same thickness, but all of the same weight! But new challenges lie ahead: cutting Swiss cheese.
Swiss cheese such as Emmentaler has holes in it, and the holes may have different sizes. A slice with holes contains less cheese and has a lower weight than a slice without holes. So here is the challenge: cut
a cheese with holes in it into slices of equal weight.
By smart sonar techniques (the same techniques used to scan unborn babies and oil fields), it is possible to locate the holes in the cheese up to micrometer precision. For the present problem you may assume that
the holes are perfect spheres.
Each uncut block has size 100×100×100 where
each dimension is measured in millimeters. Your task is to cut it into s slices
of equal weight. The slices will be 100 mm
wide and 100 mm
high, and your job is to determine the thickness of each slice.


Input

The first line of the input contains two integers n and s,
where 0≤n≤10000 is
the number of holes in the cheese, and 1≤s≤100 is
the number of slices to cut. The next n lines
each contain four positive integers r, x, y,
and z that
describe a hole, where r is
the radius and x, y,
and z are
the coordinates of the center, all in micrometers.
The cheese block occupies the points (x,y,z) where 0≤x,y,z≤100000,
except for the points that are part of some hole. The cuts are made perpendicular to the z axis.
You may assume that holes do not overlap but may touch, and that the holes are fully contained in the cheese but may touch its boundary.


Output

Display the s slice
thicknesses in millimeters, starting from the end of the cheese with z=0.
Your output should have an absolute or relative error of at most 10−6.
Sample Input 1Sample Output 1
0 4

25.000000000
25.000000000
25.000000000
25.000000000

Sample Input 2Sample Output 2
2 5
10000 10000 20000 20000
40000 40000 50000 60000

14.611103142
16.269801734
24.092457788
27.002992272
18.023645064

Download the sample data files

题意:

给出一个固定100*100*100的正方体奶酪

正方体里有很多空心球体(完全在正方体奶酪里面)

现在需要把奶酪切片,要求每片的质量(由于密度固定,所以也是体积)一样

n个空心球体,s片

n行:球体的r x y z

思路:

二分切点,切点处的体积积分求出 F()

本人提前做一次排序预处理,让球体从前到后排序,这样切点后面的空心体对体积就无影响了。做不做提前排序其实都可以,此优化并不是很必要

#include<vector>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<string>
#include<cstdio>
#include<iostream>
using namespace std;
const int MAX = 10000;
const double esp = 1e-7;
const double PI = acos(-1.0);
struct H
{
double r,x,y,z;
H(double r=0,double x=0,double y=0,double z=0):r(r),x(x),y(y),z(z) {}
};
H hole[MAX+10];
int holes,slices;//空心球的数量  和  要切的片数
bool cmp(H a,H b)
{
return (a.z-a.r)<(b.z-b.r);
}
double calculus(double r,double x)//半径,到球心的距离.。返回球体小部分的体积
{
return r*r*r*PI*2.0/3.0-r*r*x*PI+x*x*x*PI/3.0;//积分公式
}
double F(double index) //计算切点处包含的总体积
{
double weight=100*100*index;
for(int i=0;i<holes;++i){
if((hole[i].z+hole[i].r)<=index)
weight-=(PI*hole[i].r*hole[i].r*hole[i].r*4.0/3.0);//完全包括
else if(hole[i].z<=index&&(hole[i].z+hole[i].r)>=index)
weight-=(PI*hole[i].r*hole[i].r*hole[i].r*4.0/3.0-calculus(hole[i].r,index-hole[i].z) );//大半球
else if(hole[i].z>=index&&(hole[i].z-hole[i].r)<=index)
weight-=calculus(hole[i].r,hole[i].z-index); //小半球
else if((hole[i].z-hole[i].r)>index) break;
}
return weight;
}
double serch(double l,double ans) //二分切点
{
double r=100.0;
while(r-l>esp){
double mid=(l+r)/2.0;
double f=F(mid);
if(fabs(f-ans)<esp) return mid;
else if(f>ans) r=mid;
else l=mid;
}
return (l+r)/2.0;
}
void solve()
{
double sum=100.0*100.0*100.0; //奶酪总体积
for(int i=0; i<holes; ++i)
{
double xx,yy,rr,zz;
scanf("%lf%lf%lf%lf",&rr,&xx,&yy,&zz);
hole[i].r=rr/1000; hole[i].x=xx/1000; hole[i].y=yy/1000; hole[i].z=zz/1000;
sum-=(PI*hole[i].r*hole[i].r*hole[i].r*4.0/3.0);
}
if(holes>1) sort(hole,hole+holes,cmp); //提前对球体按照最左边的z值进行排序,方便二分求体积时,超出部分的球体不用计算
double last = 0,ans=sum/slices;  //last表示上一个切点   ans表示每片应该的体积
for(int i=1;i<=slices;++i)
{
if(i==slices) {printf("%.9lf\n",100-last);break;}  //最后一个的厚度
double cur=serch(last,ans*i);
printf("%.9lf\n",cur-last); //此切点减去上一个切点就是厚度
last=cur;
}
}
int main()
{
//freopen("F:\\1.txt","r",stdin);
while(scanf("%d%d",&holes,&slices)!=EOF)
{
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: