NWERC 2006 / UVa 12097 Pie (二分法求精度)

本文介绍了一个算法问题,通过使用二分查找法来确定在给定多个不同大小圆形蛋糕的情况下,如何切分蛋糕使得每个人(包括自己)都能获得尽可能大的等体积蛋糕份额。文章提供了完整的C++实现代码。

12097 - Pie

Time limit: 3.000 seconds

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=456&page=show_problem&problem=3249

 

My birthday is coming up and traditionally I'm serving pie. Not just one pie, no, I have a number N of them, of various tastes and of various sizes. F of my friends are coming to my party and each of them gets a piece of pie. This should be one piece of one pie, not several small pieces since that looks messy. This piece can be one whole pie though.

My friends are very annoying and if one of them gets a bigger piece than the others, they start complaining. Therefore all of them should get equally sized (but not necessarily equally shaped) pieces, even if this leads to some pie getting spoiled (which is better than spoiling the party). Of course, I want a piece of pie for myself too, and that piece should also be of the same size.

What is the largest possible piece size all of us can get? All the pies are cylindrical in shape and they all have the same height 1, but the radii of the pies can be different.

Input

One line with a positive integer: the number of test cases. Then for each test case:

  • One line with two integers N and F with 1 ≤ N, F ≤ 10000: the number of pies and the number of friends.
  • One line with N integers ri with 1 ≤ ri ≤ 10000: the radii of the pies.

Output

For each test case, output one line with the largest possible volume  V  such that me and my friends can all get a pie piece of size  V . The answer should be given as a floating point number with an absolute error of at most 10 -3 .

Sample Input

3
3 3
4 3 3
1 24
5
10 5
1 4 2 3 4 5 6 5 4 2

Sample Output

25.1327
3.1416
50.2655

思路:注意这题是让我们求小数形式的最优解而不是即约分数(最简分数)形式

那有更好的方法求吗?——回想高中解超越方程近似根所用的方法(二分法),我们就有了如下的代码:

/*0.029s*/

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;

const double PI = acos(-1.0);
const int maxn = 10005;

int n, f;
double A[maxn];

inline bool ok(double area)
{
	int sum = 0;
	for (int i = 0; i < n; i++)
		sum += floor(A[i] / area);
	return sum >= f + 1;
}

int main(void)
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d%d", &n, &f);
		double maxa = -1.0;
		for (int i = 0; i < n; i++)
		{
			int r;
			scanf("%d", &r);
			A[i] = PI * r * r;
			maxa = max(maxa, A[i]);
		}
		double L = 0.0, R = maxa;
		while (R - L > 1e-5)//二分查找计算,达到要求精度时停止查找
		{
			double M = (L + R) / 2;
			if (ok(M))
				L = M;
			else
				R = M;
		}
		printf("%f\n", L);
	}
	return 0;
}


### PIE 控制寄存器初始化默认值的方法 PIE(Prioritized Interrupt Controller)控制寄存器的初始化通常涉及多个方面,包括但不限于中断使能状态的保存与恢复、中断栈的配置以及中断向量表的设置。以下是关于如何将 PIE 控制寄存器初始化至默认值的具体方法: #### 1. 中断使能状态的保存与恢复 在中断处理过程中,CPU 的中断使能状态会被保存到 PIE 寄存器中以便后续恢复。此过程通过 `ICR.IE` 和 `PIE` 来实现。具体操作如下: - 在进入中断服务程序时,当前 CPU 的中断使能状态会自动被存储到 PIE 的对应位置[^1]。 - 当退出中断服务程序时,该状态会被重新加载回 CPU 的中断使能位。 因此,默认情况下无需手动干预这一部分的操作,除非需要显式禁用某些特定功能。 #### 2. 配置中断栈 (Interrupt Stack) 当程序尚未启用中断栈 (`PSW.IS = 0`) 时,可以通过以下方式完成初始化并切换到中断栈模式: - 设置 A[10] 指针指向预定义好的中断栈区域起点地址作为新的堆栈指针 ISP 值[^2]。 - 更新 PSW 寄存器中的 IS 字段为 1 表明已激活中断专用栈空间。 这一步骤对于多级嵌套中断尤为重要,因为它可以防止不同层次间相互覆盖彼此的数据结构或局部变量等内容。 #### 3. 定义及注册中断服务例程(ISRs) 为了能够响应各类硬件事件触发的不同类型的中断请IRQs, 必须事先指定好相应的ISR入口地址给定位于内存映射区内的PIE 向量表格项里去填充实际使用的函数实体链接地址(&func_name). 这一环节需要注意两点事项: - 函数名称应遵循标准 C 标识符规则; - 使用 EALLOW/EDIS 对象来保护访问权限受限资源期间所做的更改动作安全可靠.[^3] 下面给出一段伪代码展示上述逻辑: ```c // 开启全局允许修改受保护寄存器指令序列 EALLOW; // 设定外部中断线号 XINT1 所关联的服务处理器位置索引处的内容为我们自己编写的 handler_xint1 地址. PieVectTable[XINT1] = &handler_xint1; // 关闭全局允许修改受保护寄存器指令序列 EDIS; ``` 以上即完成了基本框架搭建工作. 综上所述, 要把整个系统架构下的所有可能涉及到的部分都考虑进去才能算作真正意义上的完全重设回到初始态.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值