關於 向右轉 一題的思路+程式碼(叉乘性質or解析幾何)
阿新 • • 發佈:2021-02-14
技術標籤:幾何
題目來源:NEFU OJ-760 向右轉
題目描述
相信同學們都經過軍訓,每當聽到嚴厲的教官喊“向右轉,齊步走!”,相信你沒有膽量向左轉吧!現在的問題是這樣的:給定三個點A,B,C,
教官要求你踏著正步,從A點經過B點到達C點,問該同學在B點是向右轉還是向左轉還是沿著直線走?
輸入描述
輸入資料有T(T <= 100)組,每組1行,即依次是A,B,C的座標,A,B,C的座標值均為整數,且沒有兩點的座標是重合的,資料範圍均在int內。
輸出描述
在B點如果向右轉輸出“Right”,向左轉輸出“Left”,沿著直線走則輸出“Straight”
輸入樣例
3
0 0 0 1 1 1
0 0 0 1 -1 1
0 0 0 1 0 4
輸出樣例
Right
Left
Straight
OP
下面有兩種解法,一種是通過向量叉乘的(不瞭解向量叉乘的可以戳這裡,裡面圖示非常直觀),另一種是通過解析幾何方法,不過比較麻煩。
叉乘
思路
性質,方向遵循右手定則,具體戳上面的連結即可。
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll M=10007;
int main()
{
int xa,ya,xb,yb,xc,yc,k,b,del;
cin>> xa;//原題中t可以不要
while(cin>>xa>>ya>>xb>>yb>>xc>>yc)
{
int x1,y1,x2,y2;//兩向量的座標表示
x1=xb-xa;
y1=yb-ya;
x2=xc-xb;
y2=yc-yb;
del=x1*y2-y1*x2;//計算叉乘
if(del==0)printf("Straight\n");
else if(del>0) printf("Left\n");
else printf("Right\n");
}
return 0;
}
解析幾何
思路
這個思路是沒了解叉乘之前做的,略麻煩,但是也能A。
首先進行判直,這個通過計算斜率的式子變形即可避免除0問題。
接下來進行左右判定:
在高中數學的點到直線距離公式中,分子被絕對值套住的一部分表面是防止距離變負,實際上也可以作為判定點與該直線上下關係(y軸方向)的判據(該值為正,點在直線之上;反之在之下;為0即點在線上);
這道題中左右判定除了點與線的上下關係,還需要A點與B點的左右關係;
僅說結論即為:(A在B左 && 點在線上)||(A在B右 && 點線上下)為左轉;反之為右轉。
具體實現上,我選擇用點斜式直接變形為一般式,對於斜率不存在的情況,我們可以新增一個微小的誤差,使斜率存在。
程式碼
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll M=10007;
int main()
{
double xa,ya,xb,yb,xc,yc,k,b,del;
cin>>xa;
while(cin>>xa>>ya>>xb>>yb>>xc>>yc)
{
if(fabs((ya-yb)*(xc-xb)-(yc-yb)*(xa-xb))<=0.0001)//判直
{
printf("Straight\n");
continue;
}
if(fabs(xa-xb)<=0.0001)xb+=0.0001;//新增誤差
k=(ya-yb)/(xa-xb);
b=ya-k*xa;//求直線係數
del=xb-xa;//AB相對位置
if((-k*xc+yc-b)*(del)>0)printf("Left\n");//判
else printf("Right\n");
}
return 0;
}
ED
叉乘真好用!!