bzoj4109: [Wf2015]Cutting Cheese

Description

给定一个100*100*100(单位:毫米)的奶酪方块,这个奶酪含有n个球形小孔。现在要求将这个奶酪切成s片使得每片质量相等。

Input

第一行包含两个整数n,s,表示奶酪有n个小空,要切成s片(0≤n≤10000,1≤s≤100)

接下来n行每行包含四个正整数r,x,y,z来描述每个小孔,r代表半径,(x,y,z)代表球心坐标。0≤r,x,y,z≤100,000(单位:微米)

我们假定切割必须垂直于z轴。对于小孔,孔与孔之间不会重叠(但可能相切),且每个孔都完全被奶酪包含(可能与奶酪边界相切)。

Output

从边界z=0依次输出每片的厚度(单位:毫米),输出答案与标准答案的相对误差或绝对误差不超过1e-6。

二分答案,由于球互不相交所以体积很好算,不完整的球体积用定积分可以推出公式,完整的用球的体积公式

#include<cstdio>
#include<cmath>
typedef long double ld;
const ld pi=acos(-1.);
int n,s;
ld zs[10010],rs[10010],ps[110];
ld V=1000000;
ld get(ld x){
    ld a=x*10000;
    for(int i=0;i<n;i++)if(zs[i]+rs[i]<=x){
        a-=rs[i]*rs[i]*rs[i]*(4./3.*pi);
    }else if(zs[i]-rs[i]<x){
        ld z=x-zs[i];
        a-=2./3.*pi*rs[i]*rs[i]*rs[i]+pi*(rs[i]*rs[i]*z-z*z*z/3.);
    }
    return a;
}
ld cal(ld V){
    ld L=0,R=100,M;
    while(L+1e-10<R){
        M=(L+R)*.5;
        if(get(M)<V)L=M;
        else R=M;
    }
    return L;
}
ld cals(ld x){
    ld a=10000;
    for(int i=0;i<n;i++)if(zs[i]+rs[i]>=x&&zs[i]-rs[i]<=x){
        ld z=x-zs[i];
        a-=pi*(rs[i]*rs[i]-z*z);
    }
    return a;
}
int main(){
    scanf("%d%d",&n,&s);
    for(int i=0,x;i<n;i++){
        scanf("%d",&x);
        rs[i]=x*0.001;
        scanf("%d",&x);
        scanf("%d",&x);
        scanf("%d",&x);
        zs[i]=x*0.001;
        V-=rs[i]*rs[i]*rs[i]*(4./3.*pi);
    }
    ps[0]=0;
    for(int i=1;i<=s;i++)ps[i]=cal(i*V/s);
    for(int i=1;i<=s;i++)printf("%.9Lf\n",ps[i]-ps[i-1]);
    return 0;
}
时间: 2024-10-12 16:22:33

bzoj4109: [Wf2015]Cutting Cheese的相关文章

BZOJ4115 : [Wf2015]Tile Cutting

设一种方案里三角形上三个点的坐标分别为$(0,0),(-a,b),(c,d)$,则得到的平行四边形的面积为$ac+bd$. 设$d(n)$为$n$的约数个数,$D$为$d$的生成函数,则答案的生成函数$=D^2$. 先用线性筛$O(n)$求出$d$,再用FFT在$O(n\log n)$的时间内预处理出所有答案即可. #include<cstdio> #include<cmath> #include<algorithm> #define N 1048576 using n

UVA - 10003 —— Cutting Sticks

很基础的一道区间DP :) #include <cstdio> #include <iostream> #define INF 0x3f3f3f3f using namespace std; int c[1005]; int dp[1005][1005]; int main () { int l, n; while(scanf("%d", &l)!=EOF && l) { scanf("%d", &n); fo

uva 10003 Cutting Sticks 简单区间dp

// uva 10003 Cutting Sticks 区间dp // 经典的区间dp // dp(i,j)表示切割小木棍i-j所需要的最小花费 // 则状态转移为dp(i,j) = min{dp(i,k) + dp(k,j) + a[j]-a[i]) // 其中k>i && k<j // a[j] - a[i] 为第一刀切割的代价 // a[0] = 0,a[n+1] = L; // dp数组初始化的时候dp[i][i+1]的值为 0,这表示 // 每一段都已经是切割了的,不

[2016-03-28][HDU][1078][FatMouse and Cheese]

时间:2016-03-28 17:40:34 星期一 题目编号:[2016-03-28][HDU][1078][FatMouse and Cheese] #include <algorithm> #include <cstring> #include <cstdio> using namespace std; const int maxn = 100 + 10; int a[maxn][maxn]; int dp[maxn][maxn]; int n ,k; int d

记忆化搜索,FatMouse and Cheese

1.从gird[0][0]出发,每次的方向搜索一下,每次步数搜索一下 for(i=0; i<4; i++) { for(j=1; j<=k; j++) { int tx=x+d[i][0]*j; int ty=y+d[i][1]*j; if(tx>=0&&tx<n&&ty>=0&&ty<n&&grid[x][y]<grid[tx][ty]) { int temp=memSearch(tx,ty); i

HDU1078 FatMouse and Cheese 【内存搜索】

FatMouse and Cheese Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4966    Accepted Submission(s): 2035 Problem Description FatMouse has stored some cheese in a city. The city can be considere

UVA1001 Say Cheese

如果没有洞,那么任意两点的最短距离就是直线距离,洞里是瞬间的,所以看成一个点就行了(其实点也可以当作半径为0的洞来处理),洞到洞的最短距离都是圆心距离减去半径.剩下的就是完全图求单源最短路径,用不加堆优化的dijkstra就行了O(n^2). #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 102; int x[maxn],y[maxn],z[maxn],r[maxn]; d

hdu 1078 FatMouse and Cheese

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 5701    Accepted Submission(s): 2320 Problem Description FatMouse has stored some cheese in a city. The city can be considered as a square grid of

UVa 10003 (可用四边形不等式优化) Cutting Sticks

题意: 有一个长为L的木棍,木棍中间有n个切点.每次切割的费用为当前木棍的长度.求切割木棍的最小费用. 分析: d(i, j)表示切割第i个切点到第j个切点这段所需的最小费用.则有d(i, j) = min{d(i, k) + d(k, j)} + a[j] - a[i]; ( i < k < j ) 最后一项是第一刀的费用. 时间复杂度为O(n3) 最后还要注意一下输出格式中整数后面还要加一个句点. 1 //#define LOCAL 2 #include <iostream>