(二分,数学积分)icpc2015,D.Cutting Cheese

Cutting Cheese

Problem ID: cheese Time limit: 7 seconds Memory limit: 1024 MB
DIFFICULTY
1.5
/problemimage?problem=cheese&img=/en/img-0001.jpg
Picture by Jon Sullivan via Wikimedia Commons
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  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  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

/*
题目:Cutting Cheese
链接:https://icpc.kattis.com/problems/cheese
题意:有一个100*100*100的奶酪,里面有n个不相交的圆孔,问要切成k层,每一层需要分别为多厚?
分析:二分,数学积分。
	1.用积分求不完整圆孔的体积。
	2.二分查找质量为相应质量的奶酪对应的高度,则易求得答案。
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 10005;
const double pai = acos(-1);
const double EPS = 1e-8;
typedef long long LL;
const int INF = 0xfffffff;
int input()
{
	int a;
	scanf("%d", &a);
	return a;
}
/*-------------------------------------------*/
const double daf = 100;
int N, S;
struct NODE
{
	double r, x, y, z;
}a[maxn];
vector<double> ans;
/********************************************/
double area(double r)
{
	return 4.0 / 3 * pai*r*r*r;
}
double cal(double R, double H)
{
	return 1.0 / 3 *pai* (2.0*R*R*R - 3.0*R*R*H + H*H*H);
}
double Judge(double hori)
{
	double sum = daf * daf * hori;
	for (int i = 0; i<N; i++)//对每一个圆
	{
		if (a[i].z - a[i].r >= hori)	continue;//完全在hori之上
		else if (a[i].z + a[i].r <= hori)//完全在hori之下
		{
			sum -= area(a[i].r);
		}
		else if (a[i].z>=hori&&hori >= a[i].z - a[i].r)//下半部分在hori之下
		{
			sum -= cal(a[i].r,a[i].z - hori);
		}
		else if (a[i].z+a[i].r>=hori&&hori >= a[i].z)//上半部分在hori之上
		{
			sum -= (area(a[i].r) - cal(a[i].r, hori-a[i].z));
		}
	}
	return sum;
}
void solve(double des)
{
	double l = 0, u = daf;
	while (fabs(u - l) > EPS)
	{
		double mid = (l + u) / 2;
		if (Judge(mid) > des)
			u = mid;
		else
			l = mid;
	}
	ans.push_back((l + u) / 2);
}
/********************************************/
int main()
{
//#ifdef LOCAL_JUDGE
	//freopen("f:\\input.txt", "r", stdin);
//#endif
	while (~scanf("%d%d", &N, &S))
	{
		double sum = daf * daf * daf;
		for (int i = 0; i < N; i++)
		{
			scanf("%lf%lf%lf%lf", &a[i].r, &a[i].x, &a[i].y, &a[i].z);
			a[i].r /= 1000;
			a[i].x /= 1000;
			a[i].y /= 1000;
			a[i].z /= 1000;
			sum -= area(a[i].r);
		}

		double per = sum / S;
		ans.clear();
		ans.push_back(0);
		for (int i = 1; i <= S-1; i++)
		{
			solve(per*i);
		}
		ans.push_back(100);
		for (int i = 1; i < ans.size(); i++)
		{
			printf("%.9f\n", ans[i] - ans[i - 1]);
		}
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值