题意:给出船的最大速度v,起点,终点。风在前t秒是一个方向,t秒后就一直是第二个方向。两个方向已知。

船速永远大于风速。问船在自由掌握速度和行驶方向的情况下,最快多久到终点。

分析:首先排除一种方法,那就是让船沿起点和终点的先连线线段行进,用一定的船的分速度抵消风速在行驶垂直方向的分速度。

不能这么做的原因如下,暂时我们把终点方向称作前方,而风与前方垂直的方向称为左或者右。第一个风向可能向左吹,第二个风可能向右吹,这样不需要用船速度去实时抵消风速。

即使开始被吹偏了,后来还是能被吹回来。

真正的做法是二分查找总时间。时间足够长则一定可以到达,不够长则一定不能到达。

不要担心时间太长风会把船吹得太远,因为船速是大于风速的,短时间能到达,长时间更能到达。

对于一个给定的总时间a,我们把船的位移分为三个向量之和,分别是风一和风二和船, 三者的位移。

前两个很好计算,因为方向是固定的。而第三个我们认为它是在从前两个向量之和的位置沿直线向终点前进,这是最佳策略。

我们现在只需要看船能否在a时间内走完两相量和到终点的连线。

这一题的二分查找同样使用了限制循环次数的方式来防止超时。

自由掌握方向的这种运动题,很可能需要拆分速度和位移。

#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std; #define d(x) x #define zero(x) (((x)>0?(x):-(x))<eps)
#define eps 1.0E-8
#define MAX_POINT_NUM 0 int double_cmp(double a)
{
if (zero(a))
return ;
return a > ? : -;
} struct Point
{
double x,y;
Point()
{}
Point(double x, double y):x(x), y(y)
{}
Point operator - (Point &a)
{
return Point(x - a.x, y - a.y);
}
bool operator <(const Point &a)const
{
return atan2(y, x) < atan2(a.y, a.x);
}
bool operator == (const Point &a) const
{
return x == a.x && y == a.y;
}
}; double point_dist(Point a)
{
return sqrt(a.x * a.x + a.y * a.y);
} double point_dist(Point a, Point b)
{
return point_dist(a - b);
} double dot_product(Point a, Point b)
{
return a.x * b.x + a.y * b.y;
} double dot_product(Point p0, Point p1, Point p2)
{
return dot_product(p1 - p0, p2 - p0);
} Point s, e;
Point wind1;
Point wind2;
double v, t; void input()
{
int x, y;
scanf("%d%d", &x, &y);
s = Point(x, y);
scanf("%d%d", &x, &y);
e = Point(x, y) - s;
s = Point(, );
scanf("%lf%lf", &v, &t);
scanf("%d%d", &x, &y);
wind1 = Point(x, y);
scanf("%d%d", &x, &y);
wind2 = Point(x, y); } bool ok(double a)
{
double t1 = min(a, t);
double t2 = max(a - t, 0.0);
Point by_wind = Point(t1 * wind1.x + t2 * wind2.x, t1 * wind1.y + t2 * wind2.y);
double dist = point_dist(by_wind - e);
return double_cmp(dist - v * a) <= ;
} double binary_search(double l, double r)
{
for (int i = ; i < ; i++)
{
if (double_cmp(l - r) == )
break;
double mid = (l + r) / ;
if (ok(mid))
{
r = mid;
}else
{
l = mid;
}
}
return l;
} int main()
{
input();
printf("%.18f\n", binary_search(, 1e9));
return ;
}

cf591d的更多相关文章

随机推荐

  1. 编译CM14.1(sudmod71.1)过程记录

    编译CM14.1内存要求很高,至少8G以上,我的6G也可以搞定,交换空间分配大一点. 1.安装平台 建议安装Deepin 15.3桌面版系统,系统UI好看. 2.配置环境 (1)安装编译依赖库 sud ...

  2. HTML学习笔记——标签(二)

    标签十二:<ul>标签 语义:是没有前后顺序的信息列表 语法: <ul> <li>信息</li> <li>信息</li> ... ...

  3. 小猪cms微信二次开发之怎样分页

    $db=D('Classify'); $zid=$db->where(array('id'=>$this->_GET('fid'),'token'=>$this->tok ...

  4. word中表格加粗某一行

    选中表格后选择线条粗细. 然后重新绘制一遍就行了.

  5. Javascript数组操作(转)

    1.数组的创建 var arrayObj = new Array(); //创建一个数组 var arrayObj = new Array([size]); //创建一个数组并指定长度,注意不是上限, ...

  6. 数据结构作业——buzhidao(队列)

    buzhidao Description 有一个长度为 n 的序列,第 i 个数的大小为 a[i].现在从第 1 个数开始从左往右进行以下操作:1. 如果当前数是剩下的数中最大的,则输出并删去这个数. ...

  7. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(二)

    Log4j 这个东西,大家都熟悉,就简单的介绍一下,算是一个抛砖引玉,因为我自己在Log日志的搭建方面,没有什么经验,但这东西确实是非常重要的,日后调Bug没有它基本不可能,如果有朋友有什么比较好的L ...

  8. Java中FilterInputStream和FilterOutputStream的用法

    FilterInputStream FilterInputStream 的作用是用来"封装其它的输入流,并为它们提供额外的功能".它的常用的子类有BufferedInputStre ...

  9. ASP.NET 判断客户端是否为手机的函数

    http://www.cnblogs.com/cxd4321/p/3795911.html

  10. 调用Interop.zkemkeeper.dll无法使用解决方案

    调用Interop.zkemkeeper.dll无法使用 已经注册dll成功但是还是报错 检索 COM 类工厂中 CLSID 为 {00853A19-BD51-419B--2DABE57EB61F} ...