1. 程式人生 > 其它 >關於 向右轉 一題的思路+程式碼(叉乘性質or解析幾何)

關於 向右轉 一題的思路+程式碼(叉乘性質or解析幾何)

技術標籤:幾何

題目來源: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

叉乘真好用!!