poj 3335 Rotating Scoreboard

Description

This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spectators are seated along the edges of the polygon. We want to place a rotating scoreboard somewhere in the hall such that a spectator sitting anywhere on the boundary of the hall can view the scoreboard (i.e., his line of sight is not blocked by a wall). Note that if the line of sight of a spectator is tangent to the polygon boundary (either in a vertex or in an edge), he can still view the scoreboard. You may view spectator's seats as points along the boundary of the simple polygon, and consider the scoreboard as a point as well. Your program is given the corners of the hall (the vertices of the polygon), and must check if there is a location for the scoreboard (a point inside the polygon) such that the scoreboard can be viewed from any point on the edges of the polygon.

Input

The first number in the input line, T is the number of test cases. Each test case is specified on a single line of input in the form n x1 y1 x2 y2 ... xn yn where n (3 ≤ n ≤ 100) is the number of vertices in the polygon, and the pair of integers xi yi sequence specify the vertices of the polygon sorted in order.

Output

The output contains T lines, each corresponding to an input test case in that order. The output line contains either YES or NO depending on whether the scoreboard can be placed inside the hall conforming to the problem conditions.

Sample Input

2
4 0 0 0 1 1 1 1 0
8 0 0  0 2  1 2  1 1  2 1  2 2  3 2  3 0

Sample Output

YES
NO

Source

 
求多边形是否有核。
还是半平面交,不过要判断面积为零的交是合法的、
 
 
AC CODE
  较1279改了一点点、、

program pku_3335;

const eps=1e-8;

type dotsty=record

              x,y:double;

            end;

     linesty=record

               x1,y1,x2,y2,k:double;

               sty:longint;

             end;

var line:array[1..100] of linesty;

    dot:array[1..100] of dotsty;

    q:array[1..100] of longint;

    n,cases:longint;

//============================================================================

procedure swap(x,y:longint);

var tt:linesty;

begin

  tt:=line[x]; line[x]:=line[y]; line[y]:=tt;

end;

//============================================================================

procedure qsort(l,r:longint);

var k:double;

    i,j:longint;

begin

  k:=line[(l+r) shr 1].k; i:=l; j:=r;

  repeat

    while line[i].k>k do inc(i);

    while line[j].k<k do dec(j);

    if i<=j then

    begin

      swap(i,j);

      inc(i); dec(j);

    end;

  until i>j;

  if l<j then qsort(l,j);

  if i<r then qsort(i,r);

end;

//============================================================================

procedure init;

var i,j:longint;

begin

  read(n);

  for i:=1 to n do

    read(line[i].x1,line[i].y1);

  for i:=1 to n-1 do line[i].x2:=line[i+1].x1;

  for i:=1 to n-1 do line[i].y2:=line[i+1].y1;

  line[n].x2:=line[1].x1; line[n].y2:=line[1].y1;

  for i:=1 to n do

  begin

    if (line[i].x1<line[i].x2) or

      ((line[i].x1=line[i].x2) and (line[i].y1<line[i].y2)) then

        line[i].sty:=1 else line[i].sty:=2;

    if line[i].x1<>line[i].x2 then

      line[i].k:=(line[i].y1-line[i].y2)/(line[i].x1-line[i].x2) else

        line[i].k:=maxlongint;

  end; i:=1; j:=n;

  repeat

   while line[i].sty=1 do inc(i);

   while line[j].sty=2 do dec(j);

   if i<=j then swap(i,j);

  until i>j; qsort(1,j); qsort(i,n);

end;

//============================================================================

function left(x,y:double; l:linesty):extended;

begin

  left:=(l.x2-l.x1)*(y-l.y1)-(x-l.x1)*(l.y2-l.y1);

end;

//============================================================================

function cross(l1,l2:linesty):dotsty;

var s1,s2,ss,k,dx,dy:double;

begin

  s1:=(l2.x2-l1.x1)*(l1.y2-l1.y1)-(l1.x2-l1.x1)*(l2.y2-l1.y1);

  s2:=(l1.x2-l1.x1)*(l2.y1-l1.y1)-(l2.x1-l1.x1)*(l1.y2-l1.y1);

  ss:=s1+s2;

  if abs(ss)<eps then

  begin

    cross.x:=maxlongint; exit;

  end;

  k:=s1/ss;

  dx:=l2.x1-l2.x2; dy:=l2.y1-l2.y2;

  cross.x:=l2.x2+dx*k;

  cross.y:=l2.y2+dy*k;

end;

//============================================================================

function half_plane:double;

var tmp:dotsty;

    tt:double;

    i,be,en:longint;

    flag:boolean;

begin

  be:=1; en:=1; q[1]:=1;

  for i:=2 to n do

  begin

    if sqr(line[i].x1-line[i].x2)+sqr(line[i].y1-line[i].y2)<eps then continue;

    if abs(line[q[en]].k-line[i].k)<eps then

      if left(line[q[en]].x1,line[q[en]].y1,line[i])>-eps then

        dec(en) else continue;

    while be<en do

    begin

      tmp:=cross(line[i],line[q[en]]);

      if tmp.x=maxlongint then exit(-1);

      if left(tmp.x,tmp.y,line[q[en-1]])>eps then

        dec(en) else break;

    end;

    while be<en do

    begin

      if line[i].sty=1 then break;

      if line[i].k>line[q[be]].k-eps then break;

      tmp:=cross(line[i],line[q[be]]);

      if tmp.x=maxlongint then exit(-1);

      if left(tmp.x,tmp.y,line[q[be+1]])>eps then

        inc(be) else break;

    end;

    if be<en then

    begin

      tmp:=cross(line[i],line[q[en]]);

      if tmp.x=maxlongint then exit(-1);

      if left(tmp.x,tmp.y,line[q[be]])>eps then continue;

    end; inc(en); q[en]:=i;

  end; tt:=0;

  if en<be+2 then exit(-1);

  for i:=be to en-1 do

    dot[i]:=cross(line[q[i]],line[q[i+1]]);

  dot[en]:=cross(line[q[en]],line[q[be]]);

  for i:=be to en-1 do

    tt:=tt+dot[i].x*dot[i+1].y-dot[i+1].x*dot[i].y;

  tt:=tt+dot[en].x*dot[be].y-dot[be].x*dot[en].y;

  tt:=abs(tt/2); exit(tt);

end;

//============================================================================

procedure work;

var s:double;

begin

  init;

  s:=half_plane;

  if s<-eps then writeln('NO') else writeln('YES');

end;

//============================================================================

begin

  readln(cases);

  for cases:=1 to cases do work;

end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值