【题目大意】:有一个人站在(0,0)这个点,现在要以初速度为v的飞镖去攻击位于(x,y)的苹果,问飞镖离手是与x轴的夹角。
【解题思路】:高中物理题...直接分解初速度,然后消去t...利用sin^2+cos^2=1进行化简,变形,另tana=x...暴力解一元二次方程...几行而已
第二种做法是以苹果所在的x坐标做直线,三分得到区间(p,q)此时满足当角度在p和q之间的时候可以击中苹果。
再二分区间得到最优值。
【代码】:
//数学做法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
using namespace std;
#define eps 1e-8
#define pi acos(-1.0)
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
#define g 9.8
double x,y,v,a,b,c,tmp,ans1,ans2,tanans1,tanans2;
int main() {
int T;
scanf("%d",&T);
while (T--){
scanf("%lf%lf%lf",&x,&y,&v);
a=g*x*x;
b=-2*v*v*x;
c=2*v*v*y+g*x*x;
tmp=b*b-4*a*c;
if (tmp<0) {
printf("-1\n");
continue;
}
else{
tanans1=(-b+sqrt(b*b-4*a*c))/(2*a);
tanans2=(-b-sqrt(b*b-4*a*c))/(2*a);
ans1=atan(tanans1);
ans2=atan(tanans2);
bool flag1=true,flag2=true;
if (ans1<0 || ans1>=pi/2) flag1=false;
if (ans2<0 || ans2>=pi/2) flag2=false;
if (flag1==flag2 && flag1==false) {printf("-1\n");}
else if (flag1==flag2 && flag1==true) {
if (ans1>=ans2) printf("%.6f\n",ans2);
else printf("%.6f\n",ans1);
}
else if (flag1=true) printf("%.6f\n",ans1);
else printf("%.6f\n",ans2);
}
}
return 0;
}
//二分+三分
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <cmath>
#include <string>
#include <cctype>
#include <map>
#include <iomanip>
using namespace std;
#define eps 1e-8
#define pi acos(-1.0)
#define pb push_back
#define lc(x) (x << 1)
#define rc(x) (x << 1 | 1)
#define lowbit(x) (x & (-x))
#define ll long long
#define g 9.8
double low,high,mid,mmid,x,y,v;
double tmp1,tmp2;
double check1(double a){
// double t=x/(v*cos(a));
double ans=tan(a)*x-0.5*g*x*x/v/v/cos(a)/cos(a);
return ans;
}
void get_extent(){
low=0,high=pi/2;
while (low+eps<high) {
mid=(low+high)/2.0;
mmid=(mid+high)/2.0;
tmp1=check1(mid);
tmp2=check1(mmid);
if (tmp1<tmp2) {
low=mid;
}
else {
high=mmid;
}
}
return ;
}
void get_angle(){
low=0;
while (low+eps<high){
mid=(low+high)/2.0;
tmp1=check1(mid);
if (tmp1>y) high=mid;
else low=mid;
}
printf("%.6f\n",mid);
return ;
}
int main() {
int T;
scanf("%d",&T);
while (T--){
scanf("%lf%lf%lf",&x,&y,&v);
get_extent();
if (max(tmp1,tmp2)<y) {printf("-1\n"); continue;}
else get_angle();
}
return 0;
}