题意:求人从左到右走影子的最大长度L。
设人离开灯的长度为x,当灯、人的头顶和墙角在一条直线上时(此时人在A点),影子全部投在地上,此时x = (H-h)*D/H;当人继续向前走,一部分影子就会投在墙上,当人走到最右边,影子长度即为人的高度。所以从A点到墙角,人的影子长度先增大后减小,是一个凸性函数。根据两个相似三角形把L表示成x的函数L= D+H-x-(H-h)*D/x,然后三分求解最大值。
#include <stdio.h> #include <iostream> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #define LL long long #define _LL __int64 #define eps 1e-9 using namespace std; double H,h,D; double cal(double mid) { return D+H-mid-(H-h)*D/mid; } double solve(double low, double high) { while(high - low > eps) { double mid = (low + high) / 2.0; double midmid = (mid + high) / 2.0; double ans1 = cal(mid); double ans2 = cal(midmid); if(ans1 < ans2) low = mid; else high = midmid; } return low; } int main() { int test; scanf("%d",&test); while(test--) { scanf("%lf %lf %lf",&H,&h,&D); double ans = solve((H-h)*D/H,D); printf("%.3lf\n",cal(ans)); } return 0; }
题意很简单,求出一个点x使其他所有点与该点的距离差s^3*wi最小。
#include <stdio.h> #include <iostream> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #define LL long long #define _LL __int64 #define eps 1e-8 #define PI acos(-1.0) using namespace std; const int INF = 0x3f3f3f3f; struct node { double x; double w; }p[50010]; int n; double cal(double x) { double ans = 0; for(int i = 0; i < n; i++) { double tmp = fabs(p[i].x - x); ans += tmp * tmp * tmp * p[i].w; } return ans; } double solve(double low, double high) { double ans1,ans2; while(high - low > eps) { double mid = (low+high)/2.0; double midmid = (mid + high)/2.0; ans1 = cal(mid); ans2 = cal(midmid); if(ans1 < ans2) high = midmid; else low = mid; } return low; } int main() { int test; scanf("%d",&test); double low, high; for(int item = 1; item <= test; item++) { scanf("%d",&n); low = INF; high = -INF; for(int i = 0; i < n; i++) { scanf("%lf %lf",&p[i].x,&p[i].w); low = min(low, p[i].x); high = max(high,p[i].x); } double ans = solve(low, high); printf("Case #%d: %.0lf\n",item,cal(ans)); } return 0; }
题意:给出一个直角弯道,弯道的宽分别为x和y,汽车的长和宽为l和d,问汽车能否通过弯道。
思路:
汽车要通过弯道,其左边要尽量靠着O点,右下角要尽量贴着地面。如图所示,那么在这样的情况下,汽车能通过的条件是右上角Q点到O点所在直线的距离要小于等于路的宽度y。设角度a如图,那么把要求变量表示成角度的函数 f(a) = l*cos(a) -(x - d/cos(a) ) / tan(a) 。即f(a) = l*cos(a) - (x*sin(a)-d)/sin(a)。三分法就f(a)的最大值与y比较。
#include <stdio.h> #include <iostream> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #define LL long long #define _LL __int64 #define eps 1e-8 #define PI acos(-1.0) using namespace std; const int INF = 0x3f3f3f3f; double x,y,l,w; double cal(double t) { return l*cos(t) + (w-x*cos(t))/sin(t); } double solve(double low, double high) { while(high - low > eps) { double mid= (high - low)/3+low; double midmid= (high - low)*2/3+low; double ans1 = cal(mid); double ans2 = cal(midmid); if(ans1 < ans2) low = mid; else high = midmid; } return low; } int main() { while(~scanf("%lf %lf %lf %lf",&x,&y,&l,&w)) { double low = 0; double high = acos(-1.0)/2; double ans = solve(low, high); //printf("%lf\n",ans); if(cal(ans) <= y) printf("yes\n"); else printf("no\n"); } return 0; }
时间: 2024-10-05 08:19:20