POJ 3122 Pie

题目大意:

        我的生日马上就要到了,习惯上我会请大家吃馅饼,通常不止一块而是由很多块,饼都是圆柱形的,高度都为1,各饼的半径可以不同。

        我将买N块馅饼,并且我将有F位朋友前来助兴(1 ≤ N, F ≤ 10,000),每人将得到一块饼(可能不完整),这块饼只能来自某块饼的一部分,每人只能有一块,不能超过一块,否则看上去将会很凌乱,还有就是我的朋友很在乎公平,每个人得到的饼的体积必须相同,还有就是我自己本人也要分的一块。

        现有多个测例(测例数题中会给出),每个测例中都会给出N和F的值以及各个馅饼的半径(半径都为正整数,范围为[1, 10,000]),对于每个测例,求出每个人可分的的饼的最大体积,精度为10E-3,结果截断至4位小数。

题目链接

注释代码:

/*                                 
 * Problem ID : POJ 3122 Pie 
 * Author     : Lirx.t.Una                                 
 * Language   : C                
 * Run Time   : 32 ms                                 
 * Run Memory : 216 KB                                 
*/

#include <stdio.h>

//π,AC的最低精度(测试过)
#define	PI		3.14159265359
//精度上限取题中要求的平方(10E-3)
#define	ESP		1E-6

//maximum number of people
//最大人数,包括自己
//为10,000 + 1
#define	MAXPN	10001

//volume,各个馅饼的体积
//暂存R × R的值以保证精度
//最后输出结果的时候再乘上π
int		v[MAXPN];

int
main() {

	int		t;//测例数
	int		n, f;//馅饼数和人数
	int		i;//计数变量
	int		max;//最大的馅饼的体积
	//count,记录值
	//若每人分得体积为mid时将所有馅饼用上可以分多少人
	int		cnt;

	//在实数区间上进行二分,因此取double双精度值
	//[lft, rht]表示人均分得体积的可能区间
	//mid为区间中点
	//就是在该区间上进行二分逼近结果
	double	lft, rht, mid;

	scanf("%d", &t);
	while ( t-- ) {
	
		scanf("%d%d", &n, &f);
		f++;
		for ( max = 0, i = 0; i < n; i++ ) {

			scanf("%d", v + i);
			v[i] *= v[i];//先求R的平方以保证精度
			//最后再乘上π

			if ( v[i] > max )
				max = v[i];
		}

		if ( 1 == n ) {//若只有一块饼则大家直接平分
			//避免特殊情况下还有二分,节省时间
		
			printf("%.4f\n", (double)max * PI / (double)f);
			continue;
		}

		//假设答案可能的区间为[0.0, max]
		lft = 0.0;
		rht = (double)max;

		while ( rht - lft > ESP ) {//由于浮点相减不能精确等于0
			//因此要和一个极小小数进行比较,ESP即精度极限

			mid = ( lft + rht ) / 2.0;

			for ( cnt = 0, i = 0; i < n; i++ )//计算每个饼都用上能分给多少人
				cnt += (int)( (double)v[i] / mid );

			if ( cnt >= f )//人数够
				lft = mid;//向更大探索
			else//不够分,表示人均太大
				rht = mid;//向更小探索
		}
		
		printf("%.4f\n", mid * PI);
	}

	return 0;
}

无注释代码:

#include <stdio.h>

#define	PI		3.14159265359
#define	ESP		1E-6

#define	MAXPN	10001

int		v[MAXPN];

int
main() {

	int		t;
	int		n, f;
	int		i;
	int		max;
	int		cnt;

	double	lft, rht, mid;

	scanf("%d", &t);
	while ( t-- ) {
	
		scanf("%d%d", &n, &f);
		f++;
		for ( max = 0, i = 0; i < n; i++ ) {

			scanf("%d", v + i);
			v[i] *= v[i];

			if ( v[i] > max )
				max = v[i];
		}

		if ( 1 == n ) {
		
			printf("%.4f\n", (double)max * PI / (double)f);
			continue;
		}

		lft = 0.0;
		rht = (double)max;

		while ( rht - lft > ESP ) {

			mid = ( lft + rht ) / 2.0;

			for ( cnt = 0, i = 0; i < n; i++ )
				cnt += (int)( (double)v[i] / mid );

			if ( cnt >= f )
				lft = mid;
			else
				rht = mid;
		}
		
		printf("%.4f\n", mid * PI);
	}

	return 0;
}

单词解释:

pie:n, 馅饼,饼图

come up:vi, 走近,发生

traditionally:adv, 传统上,习惯上

serve:vt, 供应,招待

messy:adj, 凌乱的,脏乱的

annoying:adj, 恼人的

complain:vt, 抱怨,发牢骚

spoil:vt, 糟蹋,溺爱

sylindrical:adj, 圆柱形的

radius:n, 半径

radii:n, 半径(复数形式)

absolute error:n, 绝对误差

volume:n, 体积

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值