hdu 4629
题意:给你n个三角形,问覆盖1~n次的面积各是多少,n < 50;
分析:取出所有端点和交点的x坐标,排序,然后对于每一段xi~xi+1的范围的线段都是不相交的,所以组成的
面积要么是三角形,要么是梯形,可以直接用公式算面积,然后对于每一个三角形的线段都标记该段对于
从下往上的扫描线来说是入边还是出边,然后就可以直接计算出这块面积被覆盖了几次;如入边加1,出边减一
下图,黄色表示覆盖次数;
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<cmath> 6 #include<vector> 7 #include<cstdlib> 8 #define pbk push_back 9 using namespace std; 10 const int N = 25050+10; 11 const double eps = 1e-10; 12 inline double sqr(double x){ 13 return x * x; 14 } 15 inline int dcmp(double x){ 16 return x < -eps ? -1 : x > eps; 17 } 18 struct Point{ 19 double x,y; 20 int kind; 21 Point(){} 22 Point(double x,double y,int kind = 0):x(x),y(y),kind(kind){} 23 bool operator < (const Point &p)const{ 24 return dcmp(x - p.x) < 0 || ( dcmp(x - p.x) == 0 && dcmp(y - p.y) < 0 ); 25 } 26 Point operator - (const Point &p)const{ 27 return Point(x - p.x, y - p.y); 28 } 29 Point operator + (const Point &p)const{ 30 return Point(x + p.x, y + p.y); 31 } 32 Point operator * (const double &k)const{ 33 return Point (x*k , y*k); 34 } 35 Point operator / (const double &k)const{ 36 return Point (x/k, y/k); 37 } 38 double operator * (const Point &p)const{ 39 return x * p.y - y * p.x; 40 } 41 double operator / (const Point &p)const{ 42 return x * p.x + y * p.y; 43 } 44 void input(){ 45 scanf("%lf%lf",&x,&y); 46 } 47 void ot(){ 48 printf("%lf %lf\n",x,y); 49 } 50 }; 51 struct Line{ 52 Point a,b; 53 int kind; 54 Line (){} 55 Line (Point a,Point b,int kind = 0):a(a),b(b),kind(kind){} 56 double operator * (const Point &p)const{ 57 return ( b - a ) * ( p - a ); 58 } 59 double operator / (const Point &p)const{ 60 return ( p - a) / ( p - b); 61 } 62 bool parallel(const Line &v){ 63 return !dcmp( ( b - a ) * ( v.b - v.a ) ); 64 } 65 int LineCrossLine(const Line &v){ 66 if ( (*this).parallel(v) ){ 67 return ( dcmp( v * a ) == 0); 68 }return 2; 69 } 70 int SegCrossSeg(const Line &v){ 71 int d1 = dcmp( (*this) * v.a); 72 int d2 = dcmp( (*this) * v.b); 73 int d3 = dcmp( v * a); 74 int d4 = dcmp( v * b); 75 if ( ( d1 ^ d2 ) == -2 && ( d3 ^ d4 ) == -2 ) return 2; 76 return ( ( d1 == 0 && dcmp( (*this) / v.a ) <= 0 ) 77 || ( d2 == 0 && dcmp( (*this) / v.b ) <= 0 ) 78 || ( d3 == 0 && dcmp( v / a ) <= 0 ) 79 || ( d4 == 0 && dcmp( v / b ) <= 0 ) 80 ); 81 } 82 Point CrossPoint(const Line &v){ 83 double s1 = v * a, s2 = v * b; 84 return ( a * s2 - b * s1) / (s2 - s1); 85 } 86 void input(){ 87 a.input(); b.input(); 88 } 89 void ot(){ 90 a.ot(); b.ot(); 91 } 92 93 }; 94 95 int n,poly_n,xn; 96 vector<double> lx; 97 vector<Line> line; 98 double ans[N]; 99 void init(){ 100 int sz = line.size(); 101 for (int i = 0; i < sz; i++){ 102 for (int j = i+1; j < sz; j++){ 103 if (line[i].SegCrossSeg(line[j]) == 2){ 104 Point p = line[i].CrossPoint(line[j]); 105 lx.pbk(p.x); 106 } 107 } 108 } 109 110 sort(lx.begin(),lx.end()); 111 xn = unique(lx.begin(),lx.end()) - lx.begin(); 112 } 113 vector<Point> qu[N]; 114 void work(){ 115 for (int i = 0; i <= n; i++) ans[i] = 0; 116 for (int i = 0; i < xn-1; i++){ 117 int k = 0; 118 for (int j = 0; j+1 < qu[i].size(); j++){ 119 k += qu[i][j].kind; 120 ans[ k ] += (lx[i+1] - lx[i]) * (qu[i][j+1].x+qu[i][j+1].y - qu[i][j].x - qu[i][j].y) / 2; 121 } 122 } 123 for (int i = 1; i <= n; i++) printf("%.10lf\n",ans[i]); 124 } 125 void check(){ 126 for (int i = 0; i < xn - 1; i++){ 127 cout<<qu[i].size()<<" >.<"<<endl; 128 for (int j = 0; j < qu[i].size(); j++){ 129 qu[i][j].ot(); cout<<qu[i][j].kind<<endl; 130 } 131 } 132 } 133 void solve(){ 134 for (int i = 0; i < xn; i++) qu[i].clear(); 135 for (int i = 0; i < line.size(); i++){ 136 int j = lower_bound(lx.begin(),lx.begin()+xn,line[i].a.x) - lx.begin(); 137 for (; j+1 < xn; j++ ){ 138 double l = lx[j], r = lx[j+1]; 139 if (dcmp(r - line[i].b.x) > 0) break; 140 Point p1 = line[i].CrossPoint(Line(Point(l,0), Point(l,1))); 141 Point p2 = line[i].CrossPoint(Line(Point(r,0), Point(r,1))); 142 qu[j].pbk(Point(p1.y, p2.y,line[i].kind)); 143 } 144 } 145 for (int i = 0; i < xn - 1; i++) sort(qu[i].begin(), qu[i].end()); 146 // check(); 147 work(); 148 } 149 int main(){ 150 int T; scanf("%d",&T); 151 while (T--){ 152 scanf("%d",&n); 153 lx.clear(); line.clear();; 154 for (int i = 0; i < n ;i++){ 155 Point t[4]; 156 for (int j = 0; j < 3; j++ ){ 157 t[j].input(); 158 } 159 t[3] = t[0]; 160 int flag = 1; 161 if (dcmp( (t[1] - t[0])*(t[2] - t[0]) ) == 0) flag = 0; 162 163 for (int i = 0; i < 3 && flag; i++ ){ 164 lx.pbk(t[i].x); 165 for (int j = i+1; j < 3; j++){ 166 Line tmp; tmp.a = t[i]; tmp.b = t[j]; 167 if (dcmp( tmp.a.x - tmp.b.x ) > 0) swap(tmp.a, tmp.b); 168 169 Line tmp2 = Line(t[3-i-j], Point(t[3-i-j].x, t[3-i-j].y - 1)); 170 if (tmp.LineCrossLine(tmp2) != 2) continue; 171 Point tp = tmp.CrossPoint(tmp2); 172 if (dcmp(tp.y - t[3-i-j].y) < 0) tmp.kind = 1; 173 else tmp.kind = -1; 174 line.pbk(tmp); 175 } 176 } 177 } 178 init(); 179 solve(); 180 } 181 return 0; 182 }