題目鏈接:https://icpc.kattis.com/problems/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 1 | Sample Output 1 |
---|---|
0 4 |
25.000000000 25.000000000 25.000000000 25.000000000 |
Sample Input 2 | Sample 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;
}