题解 P2013 【无线电测向】
计算几何水好题
读明题意后,我们可以画出以下这张图(借用样例说明):
(其中,蓝色的直线为船的航线所在的直线
紫色与红色为灯塔相对于船的方位)
不难看出,其实就是已知两条直线,求出直线的交点,即为船当前的位置!!
由平面几何中直线的定义,我们知道,对于函数f(x) ,它有一种形式叫做点斜式;
然后根据斜率的定义,我们可以求得一条直线的斜率可以以两个直线上的点的坐标决定:
那么则有:
将y 分别由x_1 ,y_1 ,x_2 ,y_2 表示得:
联立,得:
移项,得:
所以,我们只需要对于每条直线,处理出它们的斜率(即tan\alpha ,\alpha 为直线与x 轴倾斜角)
我们知道,题目给出的是航线与直线的夹角,而航线的方位是相对于
我们只需要求得该夹角的余角,即90^{\circ}-\theta (\theta 为给出的夹角)。
同时,对于直线的倾斜角,我们处理它对于
所以我们这样处理:
double beta=180-an-an2;
其中
另外,当两直线斜率相同,则无解。
完整代码:
#include<bits/stdc++.h>
#define in inline
#define reg register
#define int long long
#define MAX 20030813
#define pi acos(-1)
using namespace std;
namespace qwq{
in int read(int &o)
{
o=0;
int w=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')w=-1;
c=getchar();
}
while(c>='0'&&c<='9')
{
o=(o<<3)+(o<<1)+(c^48);
c=getchar();
}
return o*w;
}
in void write(int x)
{
if(x>9)write(x/10);
putchar(x%10+48);
}
in int max(int x,int y)
{
return x>y?x:y;
}
in int min(int x,int y)
{
return x<y?x:y;
}
}
using namespace qwq;
int n;
class Tower
{
public:
int x,y;
char cnt;
}tow[MAX];
char c1,c2;
double _x1_,_x2_,_y1_,_y2_,x,y;
int alpha,beta,an,an1,an2;
signed main()
{
read(n);
for(reg int i=1;i<=n;++i)
{
cin>>tow[i].cnt;
read(tow[i].x),read(tow[i].y);
}
read(an);
an-=90;
cin>>c1,read(an1);
alpha=180-an-an1;
cin>>c2,read(an2);
beta=180-an-an2;
if(tan(pi/180*alpha)==tan(pi/180*beta))
{
puts("NO ANSWER");return 0;
}
for(reg int i=1;i<=n;++i)
{
if(c1==tow[i].cnt)_x1_=tow[i].x,_y1_=tow[i].y;
if(c2==tow[i].cnt)_x2_=tow[i].x,_y2_=tow[i].y;
}
x=((_y2_-_y1_)+_x1_*tan(pi/180*alpha)-_x2_*tan(pi/180*beta))/(tan(pi/180*alpha)-tan(pi/180*beta));
y=_y1_+(x-_x1_)*tan(pi/180*alpha);
printf("%.2lf %.2lf\n",x,y);
return 0;
}
在楼上两篇大佬的题解里,对于灯塔位置的映射是用map 实现的,然而此题灯塔数量n\leq30 ,在下认为是不需要map 的,直接 \Theta (n) 扫描不就好啦?
若路过大佬在此停留,指点一二,蒟蒻不胜感激
Update in 19.8.15:感谢@RsXxy对于本文错误的指正。