CF717I Cowboy Beblop at his computer

Link
(poly_i(iin{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} imesvec{p_1}),这是(l=flat_0cap flat_1)的方向。
如果(|vec x|=0)那么(flat_0parallel 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}}cdotvec{p_1}))表示(a_{0,j})(flat_1)的位置关系。
(o_{0,i}=egin{cases}1& ext{above}\0& ext{on}\-1& ext{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}|=egin{cases}2& ext{intersect}\1& ext{tangent}\0& ext{apart}end{cases})
(operatorname{sgn}(e_{0,i})=egin{cases}1& ext{down}\0& ext{apart}\-1& ext{up}end{cases})
对于(e_{0,i} e0),计算得到(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}}cdotvec{p_1}}overrightarrow{a_{0,i+1}-a_{0,i}})

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

step.3

很显然所有(y_{t,i})都在(l)上,且因为相切的交点计算了两次,所以两个多边形与(l)的交点个数都是偶数。
计算出(y_{t,i})按在(vec x)方向上的坐标(pos_{t,i}=vec{y_{t,i}} imesvec x)
那么([y_{0,i}in poly_1]=|sumlimits_{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_ioverrightarrow{a_{0,i+1}-a_{0,i}}),则(overrightarrow{y_{0,i}-a_{1,0}}=overrightarrow{a_{0,i}-a_{1,0}}+k_ioverrightarrow{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}}cdotvec{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");
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12357143.html