洛谷
https://www.luogu.org/problemnew/show/P1355
判斷一個點和三角形的位置關系,最簡單的思路就是用向量。
首先排除掉和三角形頂點重合的情況。
把三角形設計成一個首尾相接的三個向量,從三個向量的起點連線到P點構成新向量,叉乘判斷方向。二維向量叉乘(x1,y1)×(x2,y2)=(x1y2-x2y1),方向是右手螺旋。那么判斷正負號就知道他們在向量的哪一側了。
在三角形中的應該在三個向量的同側。而不在三角形中的會有一個方向與另外兩個不同。在三角形上的顯然就是存在一個0。
上面的解法有一個bug,其實叉乘為0只是代表在直線上,判斷在線段上還要加一次點乘。
順便練習一波scanf,注意scanf讀入double必須是%lf,要求scanf略去字符可以參考下方寫法,注意換行符用空格略去。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct Vector{
double x,y;
Vector(double xx=0.0,double yy=0.0){x=xx,y=yy;}
Vector operator-(Vector v2){
return Vector(x-v2.x,y-v2.y);
}
bool operator==(Vector v2){
if(fabs(x-v2.x)<1e-8&&fabs(y-v2.y)<1e-8)
return true;
return false;
}
double dot(Vector v2){
return x*v2.x+y*v2.y;
}
double cross(Vector v2){
return x*v2.y-y*v2.x;
}
};
typedef Vector Point;
int main(){
Point A,B,C,P;
scanf("(%lf,%lf)",&A.x,&A.y);
scanf(" (%lf,%lf)",&B.x,&B.y);
scanf(" (%lf,%lf)",&C.x,&C.y);
scanf(" (%lf,%lf)",&P.x,&P.y);
if(A==P||B==P||C==P){
printf("4
");
return 0;
}
Vector a=C-B,b=A-C,c=B-A;
Vector pa=P-B,pb=P-C,pc=P-A;
double cross1=a.cross(pa);
double cross2=b.cross(pb);
double cross3=c.cross(pc);
if(fabs(cross1)<1e-8){
//bug在這里,叉乘為0是在直線上而非線段上
//前面判斷了在端點上的情況,所以現在只需要判斷方向
Vector t1=pa,t2=pb;
if(t1.dot(t2)<0)
printf("3
");
else
printf("2
");
return 0;
}
if(fabs(cross2)<1e-8){
//bug在這里,叉乘為0是在直線上而非線段上
//前面判斷了在端點上的情況,所以現在只需要判斷方向
Vector t1=pb,t2=pc;
if(t1.dot(t2)<0)
printf("3
");
else
printf("2
");
return 0;
}
if(fabs(cross3)<1e-8){
//bug在這里,叉乘為0是在直線上而非線段上
//前面判斷了在端點上的情況,所以現在只需要判斷方向
Vector t1=pc,t2=pa;
if(t1.dot(t2)<0)
printf("3
");
else
printf("2
");
return 0;
}
int flag1=cross1*cross2>0;
int flag2=cross2*cross3>0;
int flag3=cross3*cross1>0;
if(flag1&&flag2&&flag3){
printf("1
");
return 0;
}
printf("2
");
}
總結
- 上一篇: 农行债市宝买入到期后要到银行领取吗?
- 下一篇: 农行推出的债市宝是什么?