HDU 2298 Toxophily 【三分算法 or 直接推导物理公式】
http://acm.hdu.edu.cn/showproblem.php?pid=2298
题目大意:Bob在(0,0)点想射在(x, y)点的水果,初始的速度为v(已知), g=9.8, 求最小的角度射到苹果.
解题思路:
---直接推到物理公式:
将速度的分解为x方向和y方向,然后列出式子
1> x=vcosθ* t ----变形---> t=x/vcosθ
2> y=vsinθ*t -g*t*t/2
将t的函数带入2>式中得 y=tanθ* x-g*x*x/(2*v*v*cos^2θ) ---3式
1/cos^2θ=(sin^2θ+cos^2θ)/cos^2θ= 1+tan^2θ ----带入3式中,得:
g*x*x*tan^2θ-2*v*v*x*tanθ+g*x*x+2*v*v*y=0
将tanθ看成是未知数,那么a=g*x*x, b=-2*v*v*x, c=2*v*v*y+g*x*x;
Δ=b^2-4ac 先进行判断是否有根。如果没有根输出-1,否则根据求根公式
X1=[-b+Δ^(1/2)]/2a
X2=[-b-Δ^(1/2)]/2a
如果求的解不在[0. Π/2]内还是算无解。
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 直接推导物理公式 */ #include<stdio.h> #include<math.h> #define pi acos(-1) #define g 9.8 int main() { int T; double x, y, v; scanf("%d", &T); while(T--) { scanf("%lf%lf%lf", &x, &y, &v); double dd, x1, x2, a, b, c; a=g*x*x, b=-2*v*v*x, c=2*v*v*y+g*x*x; dd=b*b-4*a*c; if(dd<0) printf("-1\n"); else { x1=atan((-1*b+sqrt(dd))/(2*a)); x2=atan((-1*b-sqrt(dd))/(2*a)); if((x1<0||x1>pi/2)&&(x2<0||x2>pi/2)) printf("-1\n"); else if(x1<0||x1>pi/2) printf("%.6lf\n", x2); else if(x2<0||x2>pi/2) printf("%.6lf\n", x1); else printf("%.6lf\n", x1>x2?x2:x1); } } return 0; }
---三分+二分算法
--三分+二分算法
问题1》三分什么变量满足凸(凹)型函数?目的三分出什么结果
问题2》cal()里面的公式放什么,怎么推到的?
我们可以知道当θ变幻时,落在横坐标为x处的y点左边是变化的,而且呈凸形变化(我不知道怎么去证明),因此三分的对象就是θ,三分出的结果就是找出很逼近y值的角度θ。
cal()函数放的就该是根据θ,求的的y’的值,物理公式推导出y=x*tan(θ)-g*x*x/(2*v*v*cos(θ)*cos(θ));
double cal(double t)
{
return x*tan(t)-g*x*x/(2*v*v*cos(t)*cos(t));
}
PS:不得不承认画图能力很差。
然后求出的θ还要进行二分它,因为这个θ就相当于A点附近的点,即f(θ)>=y,我们从[0, θ]进行二分求出一个很接近f(θ1)~~y的θ1即相当于图中的B点。
三分+二分算法代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)