题目链接:
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=845&page=show_problem&problem=4491
#include <cstdio>
#include <algorithm>
#include <utility>
#include <cmath>
using namespace std;
pair<int,int> array[100010];
int main()
{
int n;
while(scanf("%d", &n) == 1)
{
for(int i = 0; i < n; i++)
{
scanf("%d %d", &array[i].first, &array[i].second);
}
sort(array, array+n);
double left = 0, right = 1000000, result, mid;
for(int i = 1; i <= 100; i++)
{
mid = (left+right) / 2;
double begin = 0;
int j;
for(j = 0; j < n; j++)
{
if(array[j].first > begin)
begin = array[j].first;
if(begin + mid > array[j].second)
break;
begin = begin + mid;
}
if(j == n)
{
left = mid;
result = mid;
}
else
{
right = mid;
}
}
int p = 0, q = 1;
for(int i = 1; i <= n; i++)
{
int k = round(result*i);
if(fabs((double)k/i - result) < fabs((double)p/q - result))
{
p = k;
q = i;
}
}
printf("%d/%d\n", p, q);
}
return 0;
}
这题想了很久,是不是可以用贪心做,但是没想出来。
后来看了别人的答案,发现很巧妙。先用二分查找来搜索最大可行的长度。设置迭代次数为100,足够了。
然后找到最大可行长度以后,枚举分母的所有情况,因为分母范围为1-n。
该题的启示是:
如果想不出来如何找到解,首先看看给出一个解,如何去验证。
然后再想想如何找到解,比如使用二分查找。