题意:输入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;
}
/*
3
2 6
1 4
8 12
*/