poj 1271 && uva 10117 Nice Milk (半平面交)
uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1058
半平面交求面积最值。直接枚举C(20,8)的所有情况即可。
代码如下:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 8 using namespace std; 9 10 const int N = 22; 11 struct Point { 12 double x, y; 13 Point() {} 14 Point(double x, double y) : x(x), y(y) {} 15 } pt[N], poly[N]; 16 template<class T> T sqr(T x) { return x * x;} 17 18 typedef Point Vec; 19 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);} 20 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);} 21 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);} 22 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);} 23 const double EPS = 1e-8; 24 inline int sgn(double x) { return (x > EPS) - (x < -EPS);} 25 26 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;} 27 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;} 28 inline double dotDet(Point o, Point a, Point b) { return dotDet(a - o, b - o);} 29 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);} 30 inline double vecLen(Vec x) { return sqrt(dotDet(x, x));} 31 inline Vec normal(Vec x) { return Vec(-x.y, x.x) / vecLen(x);} 32 33 struct DLine { 34 Point p; 35 Vec v; 36 double ang; 37 DLine() {} 38 DLine(Point p, Vec v) : p(p), v(v) { ang = atan2(v.y, v.x);} 39 bool operator < (const DLine &L) const { return ang < L.ang;} 40 DLine move(double x) { return DLine(p + normal(v) * x, v);} 41 } dl[N]; 42 43 inline bool onLeft(DLine L, Point p) { return crossDet(L.v, p - L.p) > 0;} 44 inline Point dLineIntersect(DLine a, DLine b) { return a.p + a.v * (crossDet(b.v, a.p - b.p) / crossDet(a.v, b.v));} 45 46 struct Poly { 47 vector<Point> pt; 48 Poly() { pt.clear();} 49 ~Poly() {} 50 Poly(vector<Point> &pt) : pt(pt) {} 51 Point operator [] (int x) const { return pt[x];} 52 int size() { return pt.size();} 53 double area() { 54 if (pt.size() < 3) return 0.0; 55 double ret = 0.0; 56 for (int i = 0, sz = pt.size(); i < sz; i++) 57 ret += crossDet(pt[i], pt[(i + 1) % sz]); 58 return fabs(ret / 2.0); 59 } 60 } ; 61 62 Point p[N]; 63 DLine q[N]; 64 int halfPlane(DLine *L, int n) { 65 sort(L, L + n); 66 int fi, la; 67 q[fi = la = 0] = L[0]; 68 for (int i = 1; i < n; i++) { 69 while (fi < la && !onLeft(L[i], p[la - 1])) la--; 70 while (fi < la && !onLeft(L[i], p[fi])) fi++; 71 q[++la] = L[i]; 72 if (fabs(crossDet(q[la].v, q[la - 1].v)) < EPS) { 73 la--; 74 if (onLeft(q[la], L[i].p)) q[la] = L[i]; 75 } 76 if (fi < la) p[la - 1] = dLineIntersect(q[la - 1], q[la]); 77 } 78 while (fi < la && !onLeft(q[fi], p[la - 1])) la--; 79 if (la < fi) return 0; 80 p[la] = dLineIntersect(q[la], q[fi]); 81 int ret = 0; 82 for (int i = fi; i <= la; i++) poly[ret++] = p[i]; 83 return ret; 84 } 85 86 //Poly halfPlane(DLine *L, int n) { 87 // Poly ret = Poly(); 88 // sort(L, L + n); 89 // int fi, la; 90 // Point *p = new Point[n]; 91 // DLine *q = new DLine[n]; 92 // q[fi = la = 0] = L[0]; 93 // for (int i = 1; i < n; i++) { 94 // while (fi < la && !onLeft(L[i], p[la - 1])) la--; 95 // while (fi < la && !onLeft(L[i], p[fi])) fi++; 96 // q[++la] = L[i]; 97 // if (fabs(crossDet(q[la].v, q[la - 1].v)) < EPS) { 98 // la--; 99 // if (onLeft(q[la], L[i].p)) q[la] = L[i]; 100 // } 101 // if (fi < la) p[la - 1] = dLineIntersect(q[la - 1], q[la]); 102 // } 103 // while (fi < la && !onLeft(q[fi], p[la - 1])) la--; 104 // if (la < fi) return ret; 105 // p[la] = dLineIntersect(q[la], q[fi]); 106 // for (int i = fi; i <= la; i++) ret.pt.push_back(p[i]); 107 // return ret; 108 //} 109 110 double polyArea(Point *p, int n) { 111 if (n < 3) return 0.0; 112 double sum = 0.0; 113 p[n] = p[0]; 114 Point O = Point(0.0, 0.0); 115 for (int i = 0; i < n; i++) sum += crossDet(O, p[i], p[i + 1]); 116 return fabs(sum / 2.0); 117 } 118 119 double work(int st, int n, double d) { 120 // cout << st << endl; 121 for (int i = 0; i < n; i++) dl[i] = DLine(pt[i], pt[i + 1] - pt[i]).move((st & (1 << i)) == 0 ? 0.0 : d); 122 int tmp = halfPlane(dl, n); 123 return polyArea(poly, tmp); 124 // Poly tmp = halfPlane(dl, n); 125 // return tmp.area(); 126 } 127 128 int cntBit(int x) { 129 int cnt = 0; 130 while (x > 0) { 131 if (x & 1) cnt++; 132 x >>= 1; 133 } 134 return cnt; 135 } 136 137 int main() { 138 // freopen("in", "r", stdin); 139 int n, k; 140 double d; 141 while (~scanf("%d%d%lf", &n, &k, &d) && (n + k + d > EPS)) { 142 for (int i = 0; i < n; i++) scanf("%lf%lf", &pt[i].x, &pt[i].y); 143 pt[n] = pt[0]; 144 double ans = 0.0, area = polyArea(pt, n); 145 for (int i = 0, end = 1 << n; i < end; i++) { 146 if (cntBit(i) <= k) { 147 // cout << i << endl; 148 ans = max(ans, area - work(i, n, d)); 149 } 150 if (sgn(ans - area) == 0) break; 151 } 152 printf("%.2f\n", ans); 153 } 154 return 0; 155 }
能通过POJ的代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 8 using namespace std; 9 10 const int N = 22; 11 struct Point { 12 double x, y; 13 Point() {} 14 Point(double x, double y) : x(x), y(y) {} 15 } pt[N], poly[N]; 16 template<class T> T sqr(T x) { return x * x;} 17 18 typedef Point Vec; 19 Vec operator + (Vec a, Vec b) { return Vec(a.x + b.x, a.y + b.y);} 20 Vec operator - (Vec a, Vec b) { return Vec(a.x - b.x, a.y - b.y);} 21 Vec operator * (Vec a, double p) { return Vec(a.x * p, a.y * p);} 22 Vec operator / (Vec a, double p) { return Vec(a.x / p, a.y / p);} 23 const double EPS = 1e-8; 24 inline int sgn(double x) { return (x > EPS) - (x < -EPS);} 25 26 inline double dotDet(Vec a, Vec b) { return a.x * b.x + a.y * b.y;} 27 inline double crossDet(Vec a, Vec b) { return a.x * b.y - a.y * b.x;} 28 inline double dotDet(Point o, Point a, Point b) { return dotDet(a - o, b - o);} 29 inline double crossDet(Point o, Point a, Point b) { return crossDet(a - o, b - o);} 30 inline double vecLen(Vec x) { return sqrt(dotDet(x, x));} 31 inline Vec normal(Vec x) { return Vec(-x.y, x.x) / vecLen(x);} 32 33 struct DLine { 34 Point p; 35 Vec v; 36 double ang; 37 DLine() {} 38 DLine(Point p, Vec v) : p(p), v(v) { ang = atan2(v.y, v.x);} 39 bool operator < (const DLine &L) const { return ang < L.ang;} 40 DLine move(double x) { return DLine(p + normal(v) * x, v);} 41 } dl[N]; 42 43 inline bool onLeft(DLine L, Point p) { return crossDet(L.v, p - L.p) > 0;} 44 inline Point dLineIntersect(DLine a, DLine b) { return a.p + a.v * (crossDet(b.v, a.p - b.p) / crossDet(a.v, b.v));} 45 46 struct Poly { 47 vector<Point> pt; 48 Poly() { pt.clear();} 49 ~Poly() {} 50 Poly(vector<Point> &pt) : pt(pt) {} 51 Point operator [] (int x) const { return pt[x];} 52 int size() { return pt.size();} 53 double area() { 54 if (pt.size() < 3) return 0.0; 55 double ret = 0.0; 56 for (int i = 0, sz = pt.size(); i < sz; i++) 57 ret += crossDet(pt[i], pt[(i + 1) % sz]); 58 return fabs(ret / 2.0); 59 } 60 } ; 61 62 Point p[N]; 63 DLine q[N], tmpDL[N]; 64 int halfPlane(DLine *L, int n) { 65 for (int i = 0; i < n; i++) tmpDL[i] = L[i]; 66 sort(L, L + n); 67 int fi, la; 68 q[fi = la = 0] = L[0]; 69 for (int i = 1; i < n; i++) { 70 while (fi < la && !onLeft(L[i], p[la - 1])) la--; 71 while (fi < la && !onLeft(L[i], p[fi])) fi++; 72 q[++la] = L[i]; 73 if (fabs(crossDet(q[la].v, q[la - 1].v)) < EPS) { 74 la--; 75 if (onLeft(q[la], L[i].p)) q[la] = L[i]; 76 } 77 if (fi < la) p[la - 1] = dLineIntersect(q[la - 1], q[la]); 78 } 79 for (int i = 0; i < n; i++) L[i] = tmpDL[i]; 80 while (fi < la && !onLeft(q[fi], p[la - 1])) la--; 81 if (la < fi) return 0; 82 p[la] = dLineIntersect(q[la], q[fi]); 83 int ret = 0; 84 for (int i = fi; i <= la; i++) poly[ret++] = p[i]; 85 return ret; 86 } 87 88 double polyArea(Point *p, int n) { 89 if (n < 3) return 0.0; 90 double sum = 0.0; 91 p[n] = p[0]; 92 Point O = Point(0.0, 0.0); 93 for (int i = 0; i < n; i++) sum += crossDet(O, p[i], p[i + 1]); 94 return fabs(sum / 2.0); 95 } 96 97 double work(int st, int n, double d) { 98 // cout << st << endl; 99 for (int i = 0; i < n; i++) dl[i] = DLine(pt[i], pt[i + 1] - pt[i]).move((st & (1 << i)) == 0 ? 0.0 : d); 100 int tmp = halfPlane(dl, n); 101 return polyArea(poly, tmp); 102 // Poly tmp = halfPlane(dl, n); 103 // return tmp.area(); 104 } 105 106 int cntBit(int x) { 107 int cnt = 0; 108 while (x > 0) { 109 if (x & 1) cnt++; 110 x >>= 1; 111 } 112 return cnt; 113 } 114 115 const double FINF = 1e100; 116 double ans, d; 117 void dfs(int id, int tt, int used, int k) { 118 if (id >= tt) { 119 int tmp = halfPlane(dl, tt); 120 ans = min(ans, polyArea(poly, tmp)); 121 return ; 122 } 123 dl[id] = DLine(pt[id], pt[id + 1] - pt[id]); 124 dfs(id + 1, tt, used, k); 125 if (used >= k) return ; 126 dl[id] = DLine(pt[id], pt[id + 1] - pt[id]).move(d); 127 dfs(id + 1, tt, used + 1, k); 128 } 129 130 int main() { 131 // freopen("in", "r", stdin); 132 int n, k; 133 while (~scanf("%d%d%lf", &n, &k, &d) && (n + k + d > EPS)) { 134 for (int i = 0; i < n; i++) scanf("%lf%lf", &pt[i].x, &pt[i].y); 135 pt[n] = pt[0]; 136 double area = polyArea(pt, n); 137 ans = FINF; 138 dfs(0, n, 0, k); 139 printf("%.2f\n", area - ans); 140 } 141 return 0; 142 }
——written by Lyon