sxbk的数学题
设每个速度向量分配到的时间为ti, 则可以列出方程:
x1t1+x2t2+...+xntn=X.........(1)
y1t1+y2t2+...+yntn-1/2*g*(t1^2+t2^2+...+tn^2)=Y.........(2)
为求出在x=X处最高点Y坐标, 可固定t3至tn, 方程组即化为二元. 令(1)式为约束, 对(2)式两侧求导
发现(t1*g-y1)/x1与(t2*g-y2)/x2的比值恒等
即(ti*g-yi)/xi = (tj*g-yj)/xj
所以二分这个比值p, 可得到最高点y值, 最低点y值可由暴力得到.
易证, 最高点y与最低点y之间都可以由这些速度向量达到
/*author: birdstorm*/
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define eps 1.0e-8
#define INF 1e50
#define g 4.9
using namespace std;
double X,Y;
int n;
struct G{
double x;
double y;
};
G d[1010];
double calc(double x)
{
double ans=0;
for(int i=0;i<n;i++){
double t=(x*d[i].x/g+d[i].y/g)/2.0;
if(t>0) ans+=t*d[i].x;
}
return ans;
}
double calcy(double x)
{
double ans=0;
for(int i=0;i<n;i++){
double t=(x*d[i].x/g+d[i].y/g)/2.0;
if(t>0) ans+=t*d[i].y-g*t*t;
}
printf("ymin=%lf\n",ans);
return ans;
}
double cnt()
{
double left=-1e4, right=1e4, mid;
while(left+eps<right){
mid=left+(right-left)/2.0;
if(calc(mid)>=X) right=mid;
else left=mid;
}
printf("left=%lf\n",left);
return calcy(left);
}
int main()
{
int i,j;
while(scanf("%d",&n),n)
{
for(i=0;i<n;i++) scanf("%lf%lf",&d[i].x,&d[i].y);
scanf("%lf%lf",&X,&Y);
//for(i=0;i<n;i++) printf("%lf %lf\n",d[i].x,d[i].y);
double ymin=INF, ymax=-INF;
for(i=0;i<n;i++){
double t1=X/d[i].x, y=d[i].y*t1-g*t1*t1;
ymin=min(y,ymin);
}
double tmp=cnt();
ymax=max(ymax,tmp);
//printf("%f %f\n",ymin,ymax);
if(Y<=ymax+eps&&Y>=ymin-eps) puts("Yes");
else puts("No");
}
return 0;
}