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 }