Caravan Robbers UVA

来源:互联网 发布:北京软件技术学院 编辑:程序博客网 时间:2024/05/17 05:53

题目传送门

题意:输入n条线段,把每一条线段的变成原线段的一条子线段,使得改变之后的线段等长且不相交(端点可以重合)。输入最大的长度。

思路:思路很简单,先排序然后二分就可以了,这个题难的是在于如何将一个小数转换为分数,一开始自己写的可能精度有些问题后来看了一下别人的思想差不多。

#include <algorithm>#include <cmath>#include <cstdio>#include <cstring>#include <fstream>#include <iostream>#include <list>#include <map>#include <queue>#include <set>#include <sstream>#include <stack>#include <string>#include <vector>#define MAXN 100010#define MAXE 10010#define INF 100000000#define MOD 1000000007#define LL long long#define pi acos(-1.0)using namespace std;struct Node{    double left;    double right;}p[MAXN];int n;bool cmp(const Node &p1, const Node &p2) {    if (p1.left == p2.left)        return p1.right < p2.right;    return p1.left < p2.left;}bool judge(double mid) {    double pos = p[0].left + mid;    if (pos > p[0].right)        return false;    for (int i = 1; i < n; ++i) {        pos = max(pos, p[i].left) + mid;        if (pos > p[i].right)            return false;    }    return true;}int main() {    std::ios::sync_with_stdio(false);    while (cin >> n) {        double left = 0, right = 0;        for (int i = 0; i < n; ++i) {            cin >> p[i].left >> p[i].right;            if (p[i].right - p[i].left > right)                right = p[i].right - p[i].left;        }        sort(p, p + n, cmp);        double mid = 0;        for (int i = 0; i < 100; ++i) {            mid = (left + right) / 2;            if (judge(mid))                left = mid;            else                right = mid;        }        int rp = 0, rq = 1;        for (int p, q = 1; q <= n; q++) {            p = round(mid * q);            if (fabs((double) p / q - mid) < fabs((double) rp / rq - mid)) {                rp = p;                rq = q;            }        }        cout << rp << "/" << rq << endl;    }    return 0;}/*32 61 48 12 */
原创粉丝点击