Hdu Toxophily【三分+二分】或者【物理公式】

 

 

题目:

Toxophily

 

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1603    Accepted Submission(s): 853

 

 

Problem Description

The recreation center of WHU ACM Team has indoor billiards, Ping Pang, chess and bridge, toxophily, deluxe ballrooms KTV rooms, fishing, climbing, and so on.
We all like toxophily.

Bob is hooked on toxophily recently. Assume that Bob is at point (0,0) and he wants to shoot the fruits on a nearby tree. He can adjust the angle to fix the trajectory. Unfortunately, he always fails at that. Can you help him?

Now given the object's coordinates, please calculate the angle between the arrow and x-axis at Bob's point. Assume that g=9.8N/m. 

 

 

Input

The input consists of several test cases. The first line of input consists of an integer T, indicating the number of test cases. Each test case is on a separated line, and it consists three floating point numbers: x, y, v. x and y indicate the coordinate of the fruit. v is the arrow's exit speed.
Technical Specification

1. T ≤ 100.
2. 0 ≤ x, y, v ≤ 10000. 

 

 

Output

For each test case, output the smallest answer rounded to six fractional digits on a separated line.
Output "-1", if there's no possible answer.

Please use radian as unit. 

 

 

Sample Input

 

3 0.222018 23.901887 121.909183 39.096669 110.210922 20.270030 138.355025 2028.716904 25.079551

 

 

Sample Output

 

1.561582 -1 -1

 

 

题目:

站在原点射箭,射箭的角度可以任意调整,且必须在0~90°之间,找出一条抛物线能经过指定的点并且射出角度最小的值。

思路 1 :

这题是一道物理题,涉及知识应该是高中比较简单的,但是,我高中的物理知识是真的忘得一干二净了,所以百度找了公式,自己瞎搞才弄出一条公式,特别费劲,公式怎么来的就不说了,我直接给出过程, 速度分解成竖直和水平两个方向,那么,水平速度为 vcos(a),竖直速度为 vsin(a),水平位移 x = vcos(a)*t , 竖直位移因为要考虑重力的影响和水平位移不同,为 y = vsin(a)*t-1/2(g*t^2); 两个式子可以削去时间t  则有公式  y = x*tan(a)-(1+tan(a)*tan(a))*(g*x*x)/(2*v*v)    (  这里有一步  省略了:1/cos^2(a)=1+tan^2(a)) 移项过后有一个一元二次方程 f(tan(a)) ,这个一元二次的 ax^2+bx+c,中的a,b,c分别移出来,可以作为判断是否存在符合题意的答案也可以通过求根公式求出答案,下面给出代码:

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<time.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<list>
#include<queue>
#include<map>
#define E exp(1)
#define PI acos(-1)
#define mod (ll)(1e9+9)
#define INF 0x3f3f3f3f;
#define MAX 40000
#define compare 0.00000001
#define exps 1e-8
//#define _CRT_SECURE_NO_WARNINGS
//#define LOCAL
using namespace std;

typedef long long ll;
typedef long double lb;

int main(void)
{
#ifdef LOCAL
	freopen("data.in.txt", "r", stdin);
	freopen("data.out.txt", "w", stdout);
#endif

	int t;
	double x, y, v, a, g = 9.8;
	
	while (scanf("%d", &t) != EOF) {
		for (int i = 0; i < t; ++i) {
			scanf("%lf%lf%lf", &x, &y, &v);
			double A =  (-1)*g * x*x / (2.0 * v*v),
				B = x,
				C = (-1)*g * x*x / (2.0 * v*v) - y,
				judge = B * B - 4 * A*C,
			
			//一元二次存在根的判断式 △	
			if (judge < 0) {
				printf("-1\n");
				continue;
			}
			
		// 这里要考虑到v如果等于0的时候,等于0的时候是不存在抛物线的 
			if (v < exps) {
				printf("-1\n");
				continue;
			}
		// 如果 x等于0,那么说明物体在正上方,
		//只要竖直射出的最高高度>=y就行了 
		//这个时候角度为90度 
			if (x < exps) {
				double min_h = (v*v) / 2 * g;
				if (y<=min_h) printf("%.6f\n", PI / 2);
				else printf("-1\n");
				continue;
			}
		//下面的就是求根公式了 
			double D = sqrt(judge);
			double t1 = (-B + D) /( 2.0 * A);
			double t2 = (-B - D) /( 2.0 * A);
	
			res_1 = 100, res_2 = 100, res;
			if (t1 >= 0 ) {
				res_1 = atan(t1);
			}
				if (t2 >= 0 ) {
					res_2 = atan(t2);
				}
				res = min(res_1, res_2);
				printf("%.6lf\n", res);
		}
	}
	//	end = clock();
	//	cout << "using tmie:" << (double)(end - start) / CLOCKS_PER_SEC * (1000) << "ms" << endl;

	//system("pause");
	return 0;
}

 

思路 2 :

 

三分+二分: 这里仍然要用到上面的公式  y = x*tan(a)-(1+tan(a)*tan(a))*(g*x*x)/(2*v*v)  ,这里的y要看成是一个因变量,x为一个常数,通过自变量 角度a 来改变y的值,那么这个公式的意思就是 一个开口向下的抛物线,且对称轴的横坐标为物体的x坐标的值,但y可能不是,可能大于物体的y坐标也可能小于物体的y坐标,我们这样要用三分的方法把 0<=a<=90度内,y值最大的那个角度找出来,当然,这个角度肯定是比较接近90度的,因为角度越高一般越高嘛,然后锁定 0<= a <= 最大角度,找出高度最接近物体y坐标的那个角度,求出来的就是答案了,找最接近的值得方法就是二分法,下面给出代码:

 

#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<time.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<list>
#include<queue>
#include<map>
#define E exp(1)
#define PI acos(-1)
#define mod (ll)(1e9+9)
#define INF 0x3f3f3f3f;
#define MAX 40000
#define compare 0.00000001
#define exps 1e-8
// 宏定义的公式
#define formula(a) x*tan(a)-(1+tan(a)*tan(a))*(g*x*x)/(2*v*v)
//#define _CRT_SECURE_NO_WARNINGS
//#define LOCAL
using namespace std;

typedef long long ll;
typedef long double lb;

int main(void)
{
#ifdef LOCAL
	freopen("data.in.txt", "r", stdin);
	freopen("data.out.txt", "w", stdout);
#endif
	int t;
	double x, y, v, g = 9.8;
	while (scanf("%d", &t) != EOF) {
		for (int i = 0; i < t; ++i) {

			scanf("%lf%lf%lf", &x, &y, &v);

			double le = 0, ri = PI / 2.0, lmid, rmid;

			while (fabs(ri-le) > exps) {
				lmid = (ri + le) / 2;
				rmid = (ri + lmid) / 2;
				if (formula(lmid) > formula(rmid)) {
					ri = rmid;
				}
				else le = lmid;
			}
		
			if (formula(ri) < y) {
				printf("-1\n");
				continue;
			}

			double mid;
			le = 0;
			mid = (le + ri) / 2;
			while (fabs(formula(mid) - y) > exps) {
				mid = (ri + le) / 2;
				if (formula(mid) > y) ri = mid;
				else le = mid;
			}
			printf("%.6lf\n", mid);
		}
	}
	//	end = clock();
	//	cout << "using tmie:" << (double)(end - start) / CLOCKS_PER_SEC * (1000) << "ms" << endl;

	//system("pause");
	return 0;
}

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值