CF717I Cowboy Beblop at his computer

Link
\(poly_i(i\in\{0,1\})\)\(n_i\)个顶点,按顺序为\(a_{i,0},\cdots,a_{i,n_i}(a_{i,n_i}=a_{i,0})\),法向量为\(\vec{p_i}\),所在平面为\(flat_i\)

step.1

计算出\(\vec x=\vec{p_0}\times\vec{p_1}\),这是\(l=flat_0\cap flat_1\)的方向。
如果\(|\vec x|=0\)那么\(flat_0\parallel flat_1\)

step.2

考虑计算\(poly_0\)的边与\(flat_1\)的交点及方向。
可以用\(o_{0,i}=\operatorname{sgn}(\cos<\overrightarrow{a_{0,i}-a_{1,0}},\vec{p_1}>)=\operatorname{sgn}(\overrightarrow{a_{0,i}-a_{1,0}}\cdot\vec{p_1})\)表示\(a_{0,j}\)\(flat_1\)的位置关系。
\(o_{0,i}=\begin{cases}1&\text{above}\\0&\text{on}\\-1&\text{below}\end{cases}\)
那么\(e_{0,i}=o_{0,i}-o_{0,i+1}\)就可以表示\(\operatorname{seg}(a_{0,i},a_{0,i+1})\)\(flat_1\)的位置关系。
\(|e_{0,i}|=\begin{cases}2&\text{intersect}\\1&\text{tangent}\\0&\text{apart}\end{cases}\)
\(\operatorname{sgn}(e_{0,i})=\begin{cases}1&\text{down}\\0&\text{apart}\\-1&\text{up}\end{cases}\)
对于\(e_{0,i}\ne0\),计算得到\(\operatorname{seg}(a_{0,i},a_{0,i+1})\cap flat_1=y_{0,i}=a_{0,i}+\frac{\overrightarrow{a_{0,i}-a_{1,0}\cdot}\vec{p_1}}{\overrightarrow{a_{0,i}-a_{1,0}}\cdot\vec{p_1}}\overrightarrow{a_{0,i+1}-a_{0,i}}\)

同理求出所有\(e_{1,i},y_{1,i}(e_{1,i}\ne0)\)

step.3

很显然所有\(y_{t,i}\)都在\(l\)上,且因为相切的交点计算了两次,所以两个多边形与\(l\)的交点个数都是偶数。
计算出\(y_{t,i}\)按在\(\vec x\)方向上的坐标\(pos_{t,i}=\vec{y_{t,i}}\times\vec x\)
那么\([y_{0,i}\in poly_1]=|\sum\limits_{pos_{1,j}<pos_{0,i}}e_{1,j}|\)

这样我们就成功地判断了\(y_{0,i}\)\(poly_1\)的位置关系,结合\(e_{0,i}\)即可算出\(poly_0\)从上往下和从下往上穿过\(poly_1\)的次数。

app.

如何得到\(y_{t,i}\)的计算式?
\(y_{0,i}=a_{0,i}+k_i\overrightarrow{a_{0,i+1}-a_{0,i}}\),则\(\overrightarrow{y_{0,i}-a_{1,0}}=\overrightarrow{a_{0,i}-a_{1,0}}+k_i\overrightarrow{a_{0,i+1}-a_{0,i}}\)
两边同时对\(\vec{p_1}\)点积得到\(k_i=\frac{\overrightarrow{a_{0,i}-a_{1,0}\cdot}\vec{p_1}}{\overrightarrow{a_{0,i}-a_{1,0}}\cdot\vec{p_1}}\)
\(y_{1,i}\)同理。

#include<cstdio>
#include<vector>
#include<utility>
#include<algorithm>
using std::pair;
using db=long double;
using i64=long long;
const int N=100007;
struct vec{i64 x,y,z;}a[2][N],p[2],x;
vec operator-(const vec&a,const vec&b){return {a.x-b.x,a.y-b.y,a.z-b.z};}
vec operator*(const vec&a,const vec&b){return {a.y*b.z-a.z*b.y,a.z*b.x-a.x*b.z,a.x*b.y-a.y*b.x};}
i64 operator^(const vec&a,const vec&b){return a.x*b.x+a.y*b.y+a.z*b.z;}
int n[2],o[N],s,t;
std::vector<pair<db,pair<int,int>>>vec;
int read(){int x;scanf("%d",&x);return x;}
int sgn(i64 x){return x<0? -1:x? 1:0;}
int main()
{
    for(int t=0;t<2;++t)
    {
	n[t]=read();
	for(int i=0;i<n[t];++i) a[t][i]={read(),read(),read()};
	a[t][n[t]]=a[t][0],p[t]=(a[t][1]-a[t][0])*(a[t][2]-a[t][0]);
    }
    if(x=p[0]*p[1],!(x^x)) return !puts("NO");
    for(int t=0;t<2;++t)
    {
	for(int i=0;i<=n[t];++i) o[i]=sgn((a[t][i]-a[t^1][0])^p[t^1]);
	for(int i=0;i<n[t];++i)
	    if(o[i]^o[i+1])
		vec.push_back({(a[t][i]^x)+((a[t][i+1]-a[t][i])^x)*(db)(p[t^1]^(a[t][i]-a[t^1][0]))/(p[t^1]^(a[t][i]-a[t][i+1])),{t,o[i]-o[i+1]}});
    }
    std::sort(vec.begin(),vec.end());
    for(auto x:vec) x.second.first? s+=t*x.second.second:t+=x.second.second;
    puts(s? "YES":"NO");
}
posted @ 2020-02-24 15:30  Shiina_Mashiro  阅读(168)  评论(0编辑  收藏  举报