UVALive4974 CERC2010B Beasts
思想是半平面交+旋转卡壳,关于X轴取一次对称再求包围(0, -10^10)点的部分后再对称回来可以少写点针对性代码。左右的射线单独处理了。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<algorithm> 5 #include<iostream> 6 #include<math.h> 7 using namespace std; 8 const int maxn = 211111; 9 const double eps = 1e-9; 10 typedef double PELEM; 11 typedef long long LL; 12 struct Point 13 { 14 PELEM x, y; 15 Point() 16 { 17 x = y = 0; 18 } 19 Point(PELEM a, PELEM b) 20 { 21 x = a, y = b; 22 } 23 PELEM cross(const Point &b, const Point &c)const 24 { 25 return (b.x - x) * (c.y - y) 26 - (c.x - x) * (b.y - y); 27 } 28 PELEM dot(const Point &p)const 29 { 30 return x * p.x + y * p.y; 31 } 32 Point operator-(const Point &p)const 33 { 34 return Point(x - p.x, y - p.y); 35 } 36 Point operator+(const Point &p)const 37 { 38 return Point(x + p.x, y + p.y); 39 } 40 Point operator-()const 41 { 42 return Point(-x, -y); 43 } 44 } p[2][maxn << 1]; 45 struct Line 46 { 47 LL a, b, c; 48 bool operator<(const Line &l)const 49 { 50 if(a *l.b == b * l.a) 51 return l.c * b < c * l.b; 52 return a * l.b > b * l.a; 53 } 54 int CmXL(const Line &l)const 55 { 56 if(a * l.b < b * l.a) return 1; 57 else if(a * l.b > b * l.a) return -1; 58 return 0; 59 } 60 bool paral(const Line &l)const 61 { 62 return a * l.b == b * l.a; 63 } 64 bool high(const Point &p)const 65 { 66 return p.x * a + p.y * b - c > eps; 67 } 68 Point CrossP(const Line &l)const 69 { 70 return Point((double)(c * l.b - l.c * b) / (a * l.b - l.a * b), 71 (double)(c * l.a - l.c * a) / (b * l.a - l.b * a)); 72 } 73 }; 74 void HPC(Line l[], int n, Point p[], Line nl[], int &pm, int &lm) 75 { 76 int i, tn; 77 sort(l, l + n); 78 pm = lm = 0; 79 nl[lm ++] = l[0]; 80 for(i = 1; i < n; ++ i) 81 { 82 if(lm && nl[lm - 1].paral(l[i])) continue; 83 while(pm && !l[i].high(p[pm - 1])) 84 -- pm, -- lm; 85 p[pm ++] = nl[lm - 1].CrossP(l[i]); 86 nl[lm ++] = l[i]; 87 } 88 if(pm == 0) p[pm ++] = Point(0, (double)nl[0].c / nl[0].b); 89 } 90 int n, pn1, pn2, ln1, ln2; 91 Line l[maxn], l1[maxn], l2[maxn]; 92 Point p1[maxn], p2[maxn]; 93 Point CrossPoint(Point a, Point b, Point c, Point d) 94 { 95 double u = a.cross(b, c), v = b.cross(a, d); 96 return Point((c.x * v + d.x * u) / (u + v), (c.y * v + d.y * u) / (u + v)); 97 } 98 double DisPtoP(Point a, Point b) 99 { 100 return (a - b).dot(a - b); 101 } 102 103 double DisPtoS(Point p, Point a, Point b, bool mk) 104 { 105 Point t = Point(p.x + a.y - b.y, p.y + b.x - a.x); 106 if(mk && (t - a).dot(b - a) > eps || t.cross(a, p) * t.cross(b, p) < -eps) 107 return DisPtoP(p, CrossPoint(t, p, a, b)); 108 return min(DisPtoP(p, a), DisPtoP(p, b)); 109 } 110 double DisStoS(Point a, Point b, Point c, Point d) 111 { 112 double ans = 1e30; 113 ans = min(ans, DisPtoS(a, c, d, 0)); 114 ans = min(ans, DisPtoS(b, c, d, 0)); 115 ans = min(ans, DisPtoS(c, a, b, 0)); 116 ans = min(ans, DisPtoS(d, a, b, 0)); 117 return ans; 118 } 119 int main() 120 { 121 int t, i, j, k; 122 double ans; 123 Point ts, te; 124 for(scanf("%d", &t); t --; ) 125 { 126 ans = 1e30; 127 scanf("%d", &n); 128 for(i = 0; i < n; ++ i) 129 { 130 scanf("%lld%lld%lld", &l[i].a, &l[i].b, &l[i].c), l[i].c = -l[i].c; 131 if(l[i].b < 0) l[i].a = -l[i].a, l[i].b = -l[i].b, l[i].c = -l[i].c; 132 } 133 HPC(l, n, p1, l1, pn1, ln1); 134 for(i = 0; i < n; ++ i) 135 l[i].a = -l[i].a, l[i].c = -l[i].c; 136 HPC(l, n, p2, l2, pn2, ln2); 137 for(i = 0; i < ln2; ++ i) 138 l2[i].a = -l2[i].a, l2[i].c = -l2[i].c; 139 for(i = 0; i < pn2; ++ i) 140 p2[i].y = -p2[i].y; 141 for(i = 0, j = pn2 - 1; i + 1 < pn1 || j;) 142 { 143 if(j && (i == pn1 - 1 || l1[i + 1].CmXL(l2[j]) == 1)) 144 ans = min(ans, DisPtoS(p1[i], p2[j - 1], p2[j], 0)), -- j; 145 else if(i < pn1 - 1 && (!j || l1[i + 1].CmXL(l2[j]) == -1)) 146 ans = min(ans, DisPtoS(p2[j], p1[i], p1[i + 1], 0)), ++ i; 147 else 148 { 149 ans = min(ans, DisStoS(p1[i], p1[i + 1], p2[j - 1], p2[j])); 150 ++ i, -- j; 151 } 152 } 153 ts = Point(p2[0].x - 1, (l2[0].c - l2[0].a * (p2[0].x - 1)) / l2[0].b); 154 te = Point(p2[pn2 - 1].x + 1, (l2[pn2].c - l2[pn2].a * (p2[pn2 - 1].x + 1)) / l2[pn2].b); 155 for(i = 0; i < pn1; ++ i) 156 { 157 ans = min(ans, DisPtoS(p1[i], p2[0], ts, 1)); 158 ans = min(ans, DisPtoS(p1[i], p2[pn2 - 1], te, 1)); 159 } 160 ts = Point(p1[0].x - 1, (l1[0].c - l1[0].a * (p1[0].x - 1)) / l1[0].b); 161 te = Point(p1[pn1 - 1].x + 1, (l1[pn1].c - l1[pn1].a * (p1[pn1 - 1].x + 1)) / l1[pn1].b); 162 for(i = 0; i < pn2; ++ i) 163 { 164 ans = min(ans, DisPtoS(p2[i], p1[0], ts, 1)); 165 ans = min(ans, DisPtoS(p2[i], p1[pn1 - 1], te, 1)); 166 } 167 printf("%.6f\n", ans); 168 } 169 return 0; 170 }