整体思路 :判凸包,然后在判断线段相交
先跑整个图的 凸包,是为了判断包含的情况
板子题
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
using namespace std;
const double eps=1e-10;
const int maxn=300;
struct point {
double x,y;
int id;
}pnt[maxn],pnt1[maxn],pnt2[maxn],res1[maxn],res2[maxn];
bool mult(point sp,point ep,point op) {
return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y);
}
bool operator <(const point &l,const point &r) {
return l.y<r.y||(l.y==r.y&&l.x<r.x);
}
int graham(point pnt[],int n,point res[]) {
int len,k=0,top=1;
memset(res,0,sizeof res);
sort(pnt,pnt+n);
if(n==0) return 0;res[0]=pnt[0];
if(n==1) return 1;res[1]=pnt[1];
if(n==2) return 2;res[2]=pnt[2];
for(int i=2; i<n; i++) {
while(top&&mult(pnt[i],res[top],res[top-1])) top--;
res[++top]=pnt[i];
}
len=top;res[++top]=pnt[n-2];
for(int i=n-3; i>=0; i--) {
while(top!=len&&mult(pnt[i],res[top],res[top-1])) top--;
res[++top]=pnt[i];
}
return top;
}
bool inter(point a,point b,point c,point d)
{
if(min(a.x,b.x)>max(c.x,d.x)||
min(a.y,b.y)>max(c.y,d.y)||
min(c.x,d.x)>max(a.x,b.x)||
min(c.y,d.y)>max(a.y,b.y)) return 0;
double h,i,j,k;
h=(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
i=(b.x-a.x)*(d.y-a.y)-(b.y-a.y)*(d.x-a.x);
j=(d.x-c.x)*(a.y-c.y)-(d.y-c.y)*(a.x-c.x);
k=(d.x-c.x)*(b.y-c.y)-(d.y-c.y)*(b.x-c.x);
return h*i<=eps&&j*k<=eps;
}
int main() {
int t,n,id;
double x,y;
cin>>t;
while(t--){
cin>>n;
memset(pnt,0,sizeof pnt);
int n1=0,n2=0;
for(int i=0;i<n;i++){
cin>>x>>y>>id;
pnt[i].x=x;pnt[i].y=y;pnt[i].id=id;
if(id==0){
pnt1[n1].x=x;pnt1[n1].y=y;pnt1[n1++].id=id;
}
else{
pnt2[n2].x=x;pnt2[n2].y=y;pnt2[n2++].id=id;
}
}
if(n==1||n==2){
cout<<1<<endl;continue;
}
if(n1==n||n2==n){cout<<1<<endl;continue;}
int m=graham(pnt,n,res1);
int cnt=0;
for(int i=0;i<m;i++) if(res1[i].id==1) cnt++;
if(cnt==0||cnt==m){cout<<0<<endl;continue;}
int m1=graham(pnt1,n1,res1);
int m2=graham(pnt2,n2,res2);
int flag=0;
for(int i=0;i<=m1-1;i++){
point a=res1[i],b;
if(i==m1-1) b=res1[0];
else b=res1[i+1];
for(int j=0;j<=m2-1;j++){
point c=res2[j],d;
if(j==m2-1) d=res2[0];
else d=res2[j+1];
if(inter(a,b,c,d)){flag=1;break;}
}
if(flag) break;
}
if(flag) cout<<0<<endl;
else cout<<1<<endl;
}
return 0;
}
本文介绍了一个算法问题的解决方法,该方法通过计算几何中的凸包算法来判断两个点集是否存在交集,并利用线段相交判断进一步确认是否发生交叉。使用Graham扫描算法找出点集的凸包,再检查凸包内的线段是否有交点。
1699

被折叠的 条评论
为什么被折叠?



