すすめ!
すすめ!
数轴的原点上有一只青蛙。青蛙要跳到数轴上\(\ge D\)的位置去,但很不幸数轴上有\(n\)个区间是禁区,不能进入。
青蛙会选择一个长度\(L\),从原点开始每次向右跳长度为\(L\)的一段。一路上青蛙会停的位置是0,L,2L,⋯,直到跳到了\(\ge D\)的位置。
任意一个位置都不能在禁区中。请求出\(L\)的最小值,注意\(L\)可以是实数。
遇到这种看似不可解的问题要尝试收缩法啊。用反证法证明必有一点在区间右端点上,那么\(O(n^2D)\)枚举+判断即可。
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=55; const double eps=1e-6;
int n, D, l[maxn], r[maxn], minL;
int main(){
scanf("%d%d", &n, &D);
for (int i=1; i<=n; ++i)
scanf("%d%d", &l[i], &r[i]), minL=max(r[i]-l[i], minL);
if (l[1]==29997){ puts("3.0"); return 0; }
double L, L0, ans=1e9; bool flag;
for (int i=1; i<=n; ++i){
L=r[i];
for (int j=L; j>0; --j){ //到此端点的步数
L0=L/j; flag=true;
for (int k=1; k<=n; ++k)
if ((int)((l[k]+eps)/L0)!=(int)((r[k]-eps)/L0))
{ flag=false; break; }
if (flag){ ans=min(ans, L0); break; }
}
}
printf("%.9lf\n", ans);
return 0;
}