UVA - 1616 Caravan Robbers 二分+暴力转换

题目大意:给出n条线段,把每条线段变成原来线段的一条子线段,使得改变后的所有线段等长且不相交,输出最大长度

解题思路:这题要用long double确保精度,精度要求很高,接下来就是将这个long double的数转化为两个整数相除的结果了,有两种方法,学习到了

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define maxn 100010
#define esp 1e-11

struct Line{
    int L, R;
}line[maxn];
int n;

bool ok(long double len) {
    long double cur = 0.0, t;
    for(int i = 0; i < n; i++) {
        t = line[i].L * 1.0;
        cur = max(t, cur);
        if(cur + len - line[i].R > esp)
            return false;
        cur += len;
    }
    return true;
}

bool cmp(const Line a, const Line b) {
    if(a.L == b.L)
        return a.R < b.R;
    return a.L < b.L;
}

int main() {

    while(scanf("%d", &n) != EOF) {
        for(int i = 0; i < n; i++)
            scanf("%d%d", &line[i].L, &line[i].R);
        sort(line, line + n, cmp);
        long double L = 0.0, R = line[n - 1].R + esp;
        while(R - L > esp) {
            long double mid = (L + R) / 2;
            if(ok(mid))
                L = mid;
            else
                R = mid;
        }
        /*
           int i;
           for(i = 1; i <= n + 1; i++) {
           int p = (int)(L * i + 0.5);
           long double t = p * 1.0 / i;
           if(t - L < 2 * esp && L - t < esp * 2)
           break;
           }
           printf("%d/%d\n", (int)(L * i + 0.5), i);
        */
        long double Min = 0x3f3f3f3f;
        int p, q;
        for(int i = 1; i <= maxn; i++) {
            int j = floor(L * i);
            if(fabs((long double)(j) / i - L) < Min) {
                p = j;
                q = i;
                Min = fabs((long double)(j) / i - L);
            }

            j = ceil(L * i);
            if(fabs((long double)(j) / i - L) < Min)    {
                p = j;
                q = i;
                Min = fabs((long double)(j) / i - L);
            }
        }
        printf("%d/%d\n", p, q);
    }
    return 0;
}
时间: 2024-12-29 04:53:01

UVA - 1616 Caravan Robbers 二分+暴力转换的相关文章

UVa 1616 Caravan Robbers (二分+贪心)

题意:给定 n 个区间,然后把它们变成等长的,并且不相交,问最大长度. 析:首先是二分最大长度,这个地方精度卡的太厉害了,都卡到1e-9了,平时一般的1e-8就行,二分后判断是不是满足不相交,找出最长的.这个题并不难, 就是精度可能控制不好,再就是把小数化成分数时,可能有点麻烦. 代码如下: #include <iostream> #include <cmath> #include <cstdlib> #include <set> #include <

UVA 1616 Caravan Robbers 商队抢劫者(二分)

依然是二分思路,但是精度要求很高需要用long double,结果要输出分数,那么就枚举一下分母,然后求出分子,在判断一下和原来的数的误差. #include<bits/stdc++.h> using namespace std; typedef long double ld; const int maxn = 1e5+5; const ld eps = 1e-11; struct Seg { int l,r; bool operator < (const Seg& x) con

UVa 1616 - Caravan Robbers

链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4491 题意: 输入n条线段,把每条线段变成原线段的一条子线段,使得改变之后所有线段等长且不相交(端点可以重合).输出最大长度(用分数表示). 分析: 二分线段的长度,然后用贪心法检验可行性,最后把小数转换为分数.这样做虽然能AC,但这也是测试数据的问题.原因是贪心的方法不完全正确.

Codeforces 778A:String Game(二分暴力)

http://codeforces.com/problemset/problem/778/A 题意:给出字符串s和字符串p,还有n个位置,每一个位置代表删除s串中的第i个字符,问最多可以删除多少个字符使得s串依旧包含p串. 思路:想到二分,以为二分做法依旧很暴力.但是别人的做法确实就是二分暴力搞啊. 枚举删除字符数,然后判断的时候如果s串包含p串,那么可以往右区间找,否则左区间找. 1 #include <bits/stdc++.h> 2 using namespace std; 3 #def

uva 1356 - Bridge(积分+二分)

题目链接:uva 1356 - Bridge 题目大意:在一座长度为B的桥上建若干个塔,塔的间距不能超过D,塔的高度为H,塔之间的绳索形成全等的抛物线.绳索的总长度为L.问在建最少塔的情况下,绳索的最下段离地面的高度. 解题思路:贪心的思想求出最少情况下建立的塔数. 二分高度,然后用积分求出两塔之间绳索的长度. C++ 积分 #include <cstdio> #include <cstring> #include <cmath> #include <algori

【UVA】12169-Disgruntled Judge(暴力or欧几里得)

可能由于后台数据的原因,这道题直接暴力枚举a,b进行判断也能过,不过跑的时间长,效率太差了. 14021006 12169 Disgruntled Judge Accepted C++ 0.876 2014-08-11 08:46:28 不说了,比较无脑. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #incl

Codeforces Round #359 (Div. 2) C. Robbers&#39; watch (暴力DFS)

题目链接:http://codeforces.com/problemset/problem/686/C 给你n和m,问你有多少对(a, b) 满足0<=a <n 且 0 <=b < m 且a的7进制和n-1的7进制位数相同 且b的7进制和m-1的7进制位数相同,还有a和b的7进制上的每位上的数各不相同. 看懂题目,就很简单了,先判断a和b的7进制位数是否超过7,不超过的话就dfs暴力枚举计算就可以了. 1 //#pragma comment(linker, "/STACK

uva 10825 - Anagram and Multiplication(暴力)

题目链接:uva 10825 - Anagram and Multiplication 题目大意:给出m和n,要求找一个m位的n进制数,要求说该数乘以2~m中的任意一个数的结果是原先数各个位上数值的一个排序. 解题思路:枚举最后一位数,然后用这个数去乘以2~m并对n取模,然后得到的数一定就是这个数的组成,暴力搜索一下并判断. #include <cstdio> #include <cstring> #include <algorithm> using namespace

uva 11256 - Repetitive Multiple(gcd+暴力)

题目链接:uva 11256 - Repetitive Multiple 题目大意:给定一个数n,要求找到最小的k,使得k?n为题目中定义的重复数字. 解题思路:枚举k?n的循环节长度,比如当前枚举为2,那么一次判断u=1001,1001001,1001001001 ...,取d = gcd(n,u), 那么k = u / d, a = n / d (因为n?k=u?a)并且保证a的长度为2,所以k和a要同时扩大相应倍数.枚举过程中为何k. #include <cstdio> #include