Problem Address:http://poj.org/problem?id=1905
【前言】
练手二分,注定悲剧的一道题。
交上去WA。
担心是精度问题,改之,再WA。
再改,TLE。
看discuss。
一大片唏嘘声。
无奈,各种TLE和WA。
一牛说要看用什么方法二分。
然后改之。
之后又是各种WA和TLE。
后来看到神贴,说原来三个数都是浮点数= =
改之,再WA。
无奈,再加上某帖的判断其中是否有零。
终于AC!
然后找到第一份代码,加上浮点数和判断,果断AC= =
最后拿到8个WA和5个TLE,以及最后的2个AC。
【思路】
第一种:对圆心角进行二分,下限0,上限为π。
第二种:对高度进行二分,下限为0,上限为rod的初始长度的二分之一。
然后是各种几何运算,判断与目标长度的关系。
精度为 1e-6 即可过。
话说还有牛顿迭代法。没试。
【代码】
第一种:对圆心进行二分。
#include <iostream>
#include <cmath>
using namespace std;
const double pi = acos(-1.0);//π的高精度,话说某道题必须是这个值才能通过= =
int main()
{
double len, n, c, length;
double low, mid, high;
double temp;
while(scanf("%lf %lf %lf", &len, &n, &c)!=EOF)
{
if (len==-1 && n==-1 && c==-1) break;
if (len==0 || n==0 || c==0)
{
printf("0.000\n");
continue;
}
length = (1.0+n*c)*(double)len;
low = 0;
high = pi;
len *= 0.5;
while(fabs(low-high)>1e-12)//估计1e-6就能通过,后来没试
{
mid = (low+high)/2;
temp = mid*len/sin(0.5*mid);
if (temp<=length)
low = mid;
else
high = mid;
}
printf("%.3lf\n", len*tan(mid*0.25));
}
return 0;
}
第二种:对高度进行二分
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
double len, n, c, length, r;
double low, mid, high;
double temp;
while(scanf("%lf %lf %lf", &len, &n, &c)!=EOF)
{
if (len==-1 && n==-1) break;
if (len==0 || n==0 || c==0)
{
printf("0.000\n");
continue;
}
length = (1.0+n*c)*(double)len;
low = 0;
high = len;
while(low<high)
{
mid = (low+high)/2;
r = mid*0.5+len*len*0.125/mid;
temp = 2.0*r*acos(1.0-mid/r);
if (fabs(temp-length)<=1e-6)
break;
else if (temp<length)
low = mid;
else
high = mid;
}
printf("%.3lf\n", mid);
}
return 0;
}
【P.S】
发现做完这道题后就可以去休息了……
本文详细记录了解决POJ 1905题目的过程,包括使用二分法寻找最佳解的过程及遇到的问题。作者尝试了两种不同的二分策略,并最终通过调整精度和增加特殊情况判断实现了正确解答。
391

被折叠的 条评论
为什么被折叠?



