poj 3122
分类: 高效搜索
题意: 有N个pie,分成F + 1份,面积相同,且每个pie必须是完整的,求最大的每个分块的面积,精确到误差小于0.001
输入: T组数据,每组数据的N,F,以及每个pie的半径,都是整数
输出: 最大的分块面积,误差小于0.001
解法:
注意: ①PI的精确程度会影响答案 ②floor函数的使用
搜索, 按照满足条件的分块搜索答案, 提高效率, 二分查找
关键在于,本题的二分如何写,解空间是多少
double findAns(double ll, double rr) { double leftVal = ll; double rightVal = rr; while (rightVal - leftVal > 1e-5) { double midVal = (leftVal + rightVal) / 2; if (isOK(midVal)) leftVal = midVal; else rightVal = midVal; } return leftVal; }
每次减少搜索范围的一部分,误差范围小于1e-5退出搜索,不同于以往的数组下标二分
#include <iostream> #include <vector> #include <map> #include <list> #include <set> #include <deque> #include <stack> #include <queue> #include <algorithm> #include <cmath> #include <cctype> #include <cstdio> #include <iomanip> #include <cmath> #include <cstdio> #include <iostream> #include <string> #include <sstream> #include <cstring> #include <queue> using namespace std; ///宏定义 const int INF = 990000000; const int MAXN = 10062; const int maxn = MAXN; ///全局变量 和 函数 int N, F; double pies[maxn]; const double PI = acos(-1.0);; bool isOK(double every) { int cnt = 0; for (int i = 0; i < N; i++) { cnt += floor(pies[i] / every); } if (cnt >= F + 1) return true; return false; } double findAns(double ll, double rr) { double leftVal = ll; double rightVal = rr; while (rightVal - leftVal > 1e-5) { // double midVal = leftVal + (rightVal - leftVal + 1) / 2; double midVal = (leftVal + rightVal) / 2; if (isOK(midVal)) leftVal = midVal; else rightVal = midVal; } return leftVal; } int main() { ///变量定义 int T; scanf("%d", &T); while (T--) { scanf("%d%d", &N, &F); double maxPie = -1; for (int i = 0; i < N; i++) { int radius; scanf("%d", &radius); pies[i] = radius * radius * PI; if (maxPie < pies[i]) maxPie = pies[i]; } double leftVal, rightVal; leftVal = 0; rightVal = maxPie; double ans = findAns(leftVal, rightVal); printf("%.5lf\n", ans); } ///结束 return 0; }