多边形链由一系列相连的线段构成,可以表示为一系列线段的端点 { A 1 , A 2 , . . . , A n } \{A_1,A_2,...,A_n\} {A1,A2,...,An} 。
给定射线 L a , b = { a + λ b ∣ λ ∈ R } L_{a,b}=\{a+\lambda b|\lambda \in \R \} La,b={a+λb∣λ∈R} ,定义多边形链 C = { A 1 , A 2 , . . . , A n } C=\{A_1,A_2,...,A_n\} C={A1,A2,...,An} 单调于射线 L a , b L_{a,b} La,b ,当且仅当:
给定 n n n 个点的多边形链 C C C ,判断是否存在射线 L a , b L_{a,b} La,b 使得多边形链 C C C 单调于射线 L a , b L_{a,b} La,b ,若有则求出任意解。
∀
v
⃗
=
A
i
A
i
+
1
(
1
≤
i
<
n
)
\forall \vec{v}=A_iA_{i+1}(1\le i
不妨对所有的
v
⃗
\vec{v}
v 求出可行的射线方向范围,然后验证是否有交集即可
当表示方向的范围时,可以用向量来保存两个边界(逆时针的最大方向与顺时针的最大方向),然后用叉乘判断交集是否存在即可。
#include
using namespace std;
template<class T>inline void read(T&x){//快读
char c,last=' ';
while(!isdigit(c=getchar()))last=c;
x=c^48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+(c^48);
if(last=='-')x=-x;
}
#define ll long long
const int MAXN=1e5+5;
int n;
struct Point{//向量表示
ll x,y;
}P[MAXN];
ll operator^(Point&a,Point&b){//叉乘,用于判断方向
return a.x*b.y-a.y*b.x;
}
int main()
{
read(n);
for(int i=1;i<=n;++i)read(P[i].x),read(P[i].y);
bool ok=0;//0表示还没有初始化
Point L={1,1},R;//若所有点都重合时,输出0 0 1 1作为答案
for(int i=1;i<n;++i){
Point p={P[i+1].x-P[i].x,P[i+1].y-P[i].y},l,r;//求出折线当前段
if(p.x==0&&p.y==0)continue;//如果两点重合,跳过
l={-p.y,p.x},r={p.y,-p.x};//l表示以当前段作为角平分线时的逆时针边界,r表示顺时针边界
if(!ok){//还没有初始化,则将当前范围直接作为交集
ok=1;
L=l,R=r;
continue;
}
if((l^R)>0&&(r^L)<0){//出现无交集的情况,即无解
puts("NO");exit(0);
}
if((l^L)>0)L=l;//逆时针边界缩小
if((r^R)<0)R=r;//顺时针边界缩小
}
puts("YES");
cout<<"0 0 "<<L.x<<' '<<L.y<<'\n';//因为是闭区间,直接取边界作为答案即可
return 0;
}