POJ3335.Rotating Scoreboard(半平面交)
题意:判断半平面交是否存在,即判断能观察到所有点的点是否存在。
下面上板子,具体看代码。
时间复杂度:
#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;
}