題意
給n個互不相包含的區間,求出一個長度的最大值,使得可以在每個區間中選出這樣一個長度的子區間,這些子區間互不相交。結果用分數表示
分析
先考慮如果給定了區間長度能不能選出這樣的區間。因爲題中說了區間互不包含,所以可以直接把所有區間先按左端點排序再按右端點排序,每個區間都儘量取靠近左端點的子區間。(如果沒有說區間不相互包含的話,就要維護優先隊列)
然後用二分可以求出這個最大長度。這個題卡精度,精度要到1e-9才能過,所以對浮點數二分時候最好直接規定二分次數,不要設EXP,就可以規避卡精度的問題。
最後是用分數表示結果。最開始想的是直接在二分的時候就直接對分母進行二分,但這樣顯然是不正確的,也得不到正確結果。對用分數表示結果的問題一般直接枚舉分母,因爲原區間的長度都是整數,最極端的情況就是1/區間數量,所以從1到n枚舉分母,然後乘以二分出來的結果算出分子。同樣這裏要處理精度問題(算出來的分數化成小數再與二分出來的結果進行比較),結果就是誤差最小的分數。
(疑問:爲什麼算分子是要四捨五入或者用天花板函數?p=round(mid*q)
p=celi(mid*q)
)
AC代碼
//UVA 1616 Caravan Robbers
//AC 2016-8-1 09:31:14
//Greedy, Binary Search, Enumeration
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <set>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <list>
#include <sstream>
#include <stack>
using namespace std;
#define cls(x) memset(x,0,sizeof x)
#define inf(x) memset(x,0x3f,sizeof x)
#define neg(x) memset(x,-1,sizeof x)
#define ninf(x) memset(x,0xc0,sizeof x)
#define st0(x) memset(x,false,sizeof x)
#define st1(x) memset(x,true,sizeof x)
#define INF 0x3f3f3f3f
#define lowbit(x) x&(-x)
#define bug cout<<"here"<<endl;
//#define debug
int n;
int gcd(int a,int b)
{
if(b==0)
return a;
return gcd(b,a%b);
}
struct interval
{
long double l,r;
bool operator< (const interval &rhs) const
{
if(l==rhs.l)
return r<rhs.r;
return l<rhs.l;
}
}inters[100010];
bool valid(long double x)
{
long double cur=0;
for(int i=0;i<n;++i)
{
cur=max(cur,inters[i].l);
cur+=x;
if(cur>inters[i].r)
return false;
}
return true;
}
int main()
{
#ifdef debug
freopen("E:\\Documents\\code\\input.txt","r",stdin);
freopen("E:\\Documents\\code\\output.txt","w",stdout);
#endif
while(cin>>n)
{
for(int i=0;i<n;++i)
cin>>inters[i].l>>inters[i].r;
sort(inters,inters+n);
long double a=0,b=1000010,mid;
for(int i=0;i<100;++i)
{
mid=(a+b)/2;
if(valid(mid))a=mid;
else b=mid;
}
int p,q=1,fp=100100,fq=1;
for(q=1;q<=n;++q)
{
p=round(mid*q);
if(fabs((long double)p/q-mid)<fabs((long double)fp/fq-mid))
{
fp=p;
fq=q;
}
}
int g=gcd(max(fp,fq),min(fp,fq));
cout<<fp/g<<"/"<<fq/g<<endl;
}
return 0;
}