2015final題 Cutting Cheese 二分切點+積分

題目鏈接: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 0n10000 is the number of holes in the cheese, and 1s100 is the number of slices to cut. The next n lines each contain four positive integers rxy, and z that describe a hole, where r is the radius and xy, and z are the coordinates of the center, all in micrometers.

The cheese block occupies the points (x,y,z) where 0x,y,z100000, 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 106.

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;
}











發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章