POJ3335.Rotating Scoreboard(半平面交)

POJ3335.Rotating Scoreboard(半平面交)

题意:判断半平面交是否存在,即判断能观察到所有点的点是否存在。

下面上板子,具体看代码。
时间复杂度: O ( n l o g n ) O(nlogn)

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=205,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
struct node{
	double x,y;
}p[N],tmp[N],newp[N];
int n,newn;
double a,b,c;
void Get_Line(node u,node v){	//已知两点u,v求直线方程ax+by+c=0 
	a=v.y-u.y;
	b=u.x-v.x;
	c=v.x*u.y-v.y*u.x;
} 
node Get_point(node u,node v){	//求直线ax+by+c 与u,v组成直线的交点. 
	double x1=a*u.x+b*u.y+c,x2=a*v.x+b*v.y+c;
	node ans;
	ans.x=(u.x*x2+v.x*x1)/(x1+x2);
	ans.y=(u.y*x2+v.y*x1)/(x1+x2);
	return ans; 
} 
void Cut(){
	int cutn=0;
	for(int i=1;i<=newn;i++){
		 if(a*newp[i].x+b*newp[i].y+c>=0)	//如果该点在半平面交内 直接加入. 
            tmp[++cutn]=newp[i];
        else		//如果不在判断两直线交点在不在. 
        {
            if(a*newp[i-1].x+b*newp[i-1].y+c>0)	//判断前一个点是否在里面,在就把两个直线交点加入. 
                tmp[++cutn]=Get_point(newp[i-1],newp[i]);//把新交点加入
            if(a*newp[i+1].x+b*newp[i+1].y+c>0)
                tmp[++cutn]=Get_point(newp[i+1],newp[i]);
        }
    }
    for(int i=1;i<=cutn;i++)	//更新每个点以及前驱,后继. 
        newp[i]=tmp[i];
    newp[cutn+1]=tmp[1],newp[0]=tmp[cutn],newn=cutn;
}
bool solve(){
	for(int i=1;i<=n;i++)
        	newp[i]=p[i];
    p[n+1]=p[1];
    newp[n+1]=newp[1],newp[0]=newp[n],newn=n;
    for(int i=1;i<=n;i++)
        Get_Line(p[i],p[i+1]),Cut();
    return newn;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
			scanf("%lf%lf",&p[i].x,&p[i].y);
		puts(solve()?"YES":"NO");
	} 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45750972/article/details/107575798
今日推荐