LA4127计算几何+离散化+点覆盖

  1 /*
  2 LA4127计算几何
  3 离散化的思想。刘的书上已经说得很清楚。
  4 重点是自己手写的函数:
  5 1、判断线段和线段的交点
  6 2、覆盖在最上面的线段的判断
  7 离散化的思想和之前做的LA2527是一致的
  8 */
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 #include <string.h>
 12 #include <math.h>
 13 #include <ctype.h>
 14 #include <string>
 15 #include <iostream>
 16 #include <sstream>
 17 #include <vector>
 18 #include <queue>
 19 #include <stack>
 20 #include <map>
 21 #include <list>
 22 #include <set>
 23 #include <algorithm>
 24 #define INF 0x3f3f3f3f
 25 #define eps 1e-7
 26 #define eps2 1e-3
 27 #define zero(x) (((x)>0?(x):-(x))<eps)
 28 using namespace std;
 29 
 30 
 31 struct Point
 32 {
 33     double x,y;
 34     Point() {}
 35     Point(double xx,double yy)
 36     {
 37         x=xx;
 38         y=yy;
 39     }
 40     bool operator<(const Point& p) const{
 41         if (x==p.x) return y<p.y;
 42         else return x<p.x;
 43     }
 44 };
 45 
 46 typedef Point Vector;
 47 
 48 struct Segment
 49 {
 50     Point p1,p2;
 51     Segment(){}
 52     Segment(Point p11,Point p22)
 53     {
 54         p1=p11;p2=p22;
 55     }
 56     double getk()
 57     {
 58         return (p1.y-p2.y)/(p1.x-p2.x);
 59     }
 60 }Seg[25005];
 61 
 62 struct Line
 63 {
 64     Point p;
 65     Vector v;
 66     Line(){}
 67     Line(Point pp,Vector vv)
 68     {
 69         v=vv;
 70         p=pp;
 71     }
 72 };
 73 bool operator==(Point A,Point B)
 74 {
 75     if ((fabs(A.x-B.x)<eps) && (fabs(A.y-B.y)<eps)) return true;
 76     else return false;
 77 }
 78 Vector operator-(Point A,Point B)//表示A指向B
 79 {
 80     return Vector(A.x-B.x,A.y-B.y);
 81 }
 82 Vector operator*(Vector A,double k)
 83 {
 84     return Vector(A.x*k,A.y*k);
 85 }
 86 Vector operator+(Point A,Point B)//表示A指向B
 87 {
 88     return Vector(B.x+A.x,B.y+A.y);
 89 }
 90 double Dot(Vector A,Vector B)
 91 {
 92     return A.x*B.x+A.y*B.y;
 93 }
 94 double Length(Vector A)
 95 {
 96     return sqrt(Dot(A,A));
 97 }
 98 double Cross(Vector A,Vector B)
 99 {
100     return A.x*B.y-A.y*B.x;
101 }
102 double Area2(Point A,Point B,Point C)
103 {
104     return Cross(B-A,C-A);
105 }
106 int dcmp(double x)
107 {
108     if(fabs(x)<eps) return 0;
109     else if(x>0) return 1;
110     else return -1;
111 }
112 double angle(Vector v)
113 {
114     return atan2(v.y,v.x);
115 }
116 Vector Rotate(Vector A,double rad)//向量向逆时针旋转
117 {
118     return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));
119 }
120 Point InterSection(Line L1,Line L2)//求直线交点
121 {
122     Vector u=L1.p-L2.p;
123     double t=Cross(L2.v,u)/Cross(L1.v,L2.v);
124     return L1.p+L1.v*t;
125 }
126 bool SegInter(Segment l1,Segment l2,double* xx)
127 {
128     Point jiao=(InterSection(Line(l1.p1,l1.p2-l1.p1),Line(l2.p1,l2.p2-l2.p1)));
129     *xx=jiao.x;
130     if ( *xx-l1.p1.x>=0 && l1.p2.x-*xx>=0 && *xx-l2.p1.x>=0 && l2.p2.x-*xx>=0) return true;else return false;
131 }
132 int findUpesetLine(int cnt,double a)//线段个数,中点横坐标,返回最上(后)覆盖这个点的线段序号
133 {
134     int ans=-1;
135     double my=-1;
136     for(int i=0;i<cnt;i++)
137     {
138         double x1=Seg[i].p1.x,y1=Seg[i].p1.y,x2=Seg[i].p2.x,y2=Seg[i].p2.y;
139         if (x1-a>0 || a-x2>0) continue;
140         double k1=x1-a,k2=x2-a;
141         double y=(k2*y1-k1*y2)/(-k1+k2);
142         if (y-my>0)
143         {
144             my=y;
145             ans=i;
146         }
147     }
148     return ans;
149 }
150 int n,cas=0;
151 double x,h,b;
152 double X[25500];//离散的x坐标
153 int main()
154 {
155     double ans=0;
156     int cnt=0;//线段的个数
157     int cnt2=0;//离散点的个数
158     while(cin>>n && n>0)
159     {
160         cas++;
161         ans=0;
162         cnt=cnt2=0;
163         for(int i=0;i<n;i++)//预处理
164         {
165             cin>>x>>h>>b;
166             b=b/2;
167             Seg[cnt++]=Segment(Point(x-b,0),Point(x,h));
168             Seg[cnt++]=Segment(Point(x,h),Point(x+b,0));
169             X[cnt2++]=x-b;X[cnt2++]=x;X[cnt2++]=x+b;
170         }
171         for(int i=1;i<cnt;i++)
172         for(int j=0;j<i;j++)//线段两两求交点
173         {
174             double xx;
175             bool ok=SegInter(Seg[i],Seg[j],&xx);
176             if (ok) X[cnt2++]=xx;
177         }
178         sort(X,X+cnt2);
179 //        for(int i=0;i<cnt2;i++) cout<<X[i]<<" ";cout<<endl;
180         for(int i=0;i<cnt2-1;i++)//枚举每两个相邻离散线段的中点
181         {
182             double px=(X[i]+X[i+1])/2;
183             int num=findUpesetLine(cnt,px);
184             if (num!=-1){
185                 double k=Seg[num].getk();//用斜率求线段长度
186                 ans+=(X[i+1]-X[i])*sqrt(1+k*k);
187             }
188         }
189         printf("Case %d: %d\n\n",cas,(int)(ans+0.5));
190     }
191 
192 }

 

posted @ 2014-02-28 13:03  little_w  阅读(451)  评论(0编辑  收藏  举报