zoukankan      html  css  js  c++  java
  • USACO 3.4.1 fence4

    题目:

    http://ace.delos.com/usacoprob2?a=hgHbW0wyBLd&S=fence4

    http://www.nocow.cn/index.php/Translate:USACO/fence4

    Closed Fences

    A closed fence in the plane is a set of non-crossing, connected line segments with N corners (3 < N < 200). The corners or vertices are each distinct and are listed in counter-clockwise order in an array {xi, yi}, i in (1..N).

    Every pair of adjacent vertices defines a side of the fence. Thus {xi yi xi+1 yi+1} is a side of the fence for all i in (1..N). For our purposes, N+1 = 1, so that the first and last vertices making the fence closed.

    Here is a typical closed fence and a point x,y:

    
    
                             * x3,y3
                     x5,y5  / \
        x,y *          *   /   \
                      / \ /     \
                     /   *       \
               x6,y6*   x4,y4     \
                    |              \
                    |               \
               x1,y1*----------------* x2,y2
     

    Write a program which will do the following:

    • Test an ordered list of vertices {xi,yi}, i in (1..N) to see if the array is a valid fence.
    • Find the set of fence sides that a person (with no height) who is standing in the plane at position (x,y) can "see" when looking at the fence. The location x,y may fall anywhere not on the fence.

    A fence side can be seen if there exists a ray that connects (x,y) and any point on the side, and the ray does not intersect any other side of the fence. A side that is parallel to the line of sight is not considered visible. In the figure, above the segments x3,y3-x4,y4; x5,y5-x6,y6; and x6-y6-x1,y1 are visible or partially visible from x,y.

    PROGRAM NAME: fence4

    INPUT FORMAT

    Line 1: N, the number of corners in the fence
    Line 2: Two space-separated integers, x and y, that are the location of the observer. Both integers will fit into 16 bits.
    Line 3-N+2: A pair of space-separated integers denoting the X,Y location of the corner. The pairs are given in counterclockwise order. Both integers are no larger than 1000 in magnitude.

    NOTE: I have added anNew test case #12 for this task. Let me know if you think it's wrong. Rob Be sure to include USACO in your mail subject!

    SAMPLE INPUT (file fence4.in)

    13
    5 5
    0 0
    7 0
    5 2
    7 5
    5 7
    3 5
    4 9
    1 8
    2 5
    0 9
    -2 7
    0 3
    -3 1 
    

    OUTPUT FORMAT

    If the sequence is not a valid fence, the output is a single line containing the word "NOFENCE".

    Otherwise, the output is a listing of visible fence segments, one per line, shown as four space-separated integers that represent the two corners. Express the points in the segment by showing first the point that is earlier in the input, then the point that is later. Sort the segments for output by examining the last point and showing first those points that are earlier in the input. Use the same rule on the first of the two points in case of ties.

    SAMPLE OUTPUT (file fence4.out)

    7
    0 0 7 0
    5 2 7 5
    7 5 5 7
    5 7 3 5
    -2 7 0 3
    0 0 -3 1
    0 3 -3 1

    题解:
      这题是一道恶心的计算几何题,当初做USACO的时候做到这道题就不想做了,于是乎USACO的进度就这样被耽搁了下来。近来终于又重新开始做这道题,在参考了ymf大神的题解之后终于找到一种比较好的写法了。

      我们考虑从所在地能否看到某一条线段,如果说该线段的左端点和右端点都被同一条线段挡住的话,那么该条线段是不可能被看见的。如果这两个点没有被任何一条线段挡住,那么也就说明这条线段是可见的。如果同时不满足上述两个条件,我们就需要将这条线段砍成两半,用同样的方法检验新的两条线段是否可见,那么这样我们便可以求出一条线段是否可见了。

      其实这题思路并不复杂,也不难写,但是计算几何总让人感觉很恶心。另外由于数据中没有NOFENCE的情况,我就偷偷懒,没有判断了。

    View Code
      1 /*
      2 ID:zhongha1
      3 PROB:fence4
      4 LANG:C++
      5 */
      6 
      7 #include<cstdio>
      8 #include<cstdlib>
      9 #include<cstring>
     10 #include<cmath>
     11 #include<algorithm>
     12 
     13 using namespace std;
     14 
     15 const double eps=1e-6;
     16 const int maxn=300;
     17 
     18 int n;
     19 
     20 bool seg_seen[maxn];
     21 
     22 struct point
     23 {
     24        double x,y;
     25        point()
     26        {
     27               x=y=0.0;
     28        }
     29        point(double a,double b)
     30        {
     31            x=a;y=b;
     32        }
     33        void init()
     34        {
     35             scanf("%lf%lf",&x,&y);
     36        }
     37 }eye,tmp;
     38 
     39 struct line
     40 {
     41        point sp,ep;
     42        void print()
     43        {
     44            printf("%.0lf %.0lf %.0lf %.0lf\n",sp.x,sp.y,ep.x,ep.y);
     45        }
     46 }ed[maxn];
     47 
     48 void init()
     49 {
     50      scanf("%d",&n);
     51      eye.init();
     52      tmp.init();
     53      for (int a=1;a<n;a++)
     54      {
     55          point ep;
     56          ep.init();
     57          ed[a].sp=tmp;
     58          ed[a].ep=ep;
     59          tmp=ep;
     60      }
     61      ed[n].sp=ed[n-1].ep;
     62      ed[n].ep=ed[1].sp;
     63      swap(ed[n].sp,ed[n].ep);
     64 }
     65 
     66 point get_mid(line a)
     67 {
     68     point x;
     69     x.x=(a.ep.x+a.sp.x)/2.0;
     70     x.y=(a.ep.y+a.sp.y)/2.0;
     71     return x;
     72 }
     73 
     74 bool same(point a,point b)
     75 {
     76      if (fabs(a.x-b.x)>=eps) return false;
     77      if (fabs(a.y-b.y)>=eps) return false;
     78      return true;
     79 }
     80 
     81 double det(point a,point b)
     82 {
     83     return a.x*b.y-a.y*b.x;
     84 }
     85 
     86 bool diff_side(line a,line b)
     87 {
     88     point x;
     89     x=point(a.ep.x-a.sp.x,a.ep.y-a.sp.y);
     90     double t1=det(x,point(b.sp.x-a.sp.x,b.sp.y-a.sp.y));
     91     double t2=det(x,point(b.ep.x-a.sp.x,b.ep.y-a.sp.y));
     92     if (t1*t2<=0) return true;
     93     return false;
     94 }
     95 
     96 bool seg_cross(line a,line b)
     97 {
     98     return (diff_side(a,b) && diff_side(b,a));
     99 }
    100 
    101 bool lookat(point eye,int nowp,line now)
    102 {
    103     if (same(now.ep,now.sp)) return false;
    104     bool able=false;
    105     line lline,rline;
    106     lline.sp=rline.sp=eye;
    107     lline.ep=now.sp;rline.ep=now.ep;
    108     for (int a=1;a<=n;a++)
    109         if (a!=nowp)
    110         {
    111             bool able1=seg_cross(lline,ed[a]);
    112             bool able2=seg_cross(rline,ed[a]);
    113             if (able1 && able2) return false;
    114             able|=able1 || able2;
    115         }
    116     if (!able) return true;
    117     lline.sp=now.sp;
    118     rline.sp=now.ep;
    119     lline.ep=rline.ep=get_mid(now);
    120     if (lookat(eye,nowp,lline)) return true;
    121     if (lookat(eye,nowp,rline)) return true;
    122     return false;
    123 }
    124 
    125 int main()
    126 {
    127     freopen("fence4.in","r",stdin);
    128     freopen("fence4.out","w",stdout);
    129     
    130     init();
    131     for (int a=1;a<=n;a++)
    132         seg_seen[a]=lookat(eye,a,ed[a]);
    133     int sum=0;
    134     for (int a=1;a<=n;a++)
    135         sum+=seg_seen[a];
    136     printf("%d\n",sum);
    137     for (int a=1;a<=n-2;a++)
    138         if (seg_seen[a]) ed[a].print();
    139     if (seg_seen[n]) ed[n].print();
    140     if (seg_seen[n-1]) ed[n-1].print();
    141     
    142     return 0;
    143 }
    
    
    
     

     

  • 相关阅读:
    MongoDB索引实战技巧
    解决scp/ssh提示输密码慢问题
    mac系统忘记root密码的解决办法
    Javascript DataGrid using the MVC
    便捷的安全检测
    北京出现NW28开头假钞 天津已有相同案例
    12月编程语言排行榜:C#前途无量
    实时股票数据接口大全
    [一定要看完]住在隔壁的刚毕业的大学生小夫妻
    [行業]金山卫士宣布开源 用透明对抗360
  • 原文地址:https://www.cnblogs.com/zhonghaoxi/p/2519194.html
Copyright © 2011-2022 走看看