51NOD - 1976 多边形划分

给一个共有 n个点的凸多边形,求一条将该多边形划分为面积和周长都相等的两部分的直线。
Input
第一行一个正整数n,表示多边形的点数。(n <= 40000)
接下来的n行,第i+1行,每行两个实数xi,yi,表示凸多边形的一个点的坐标,点按照逆时针或顺时针的顺序给出。
其中n,|xi|,|yi|<=40000。
Output
如果存在这样的直线,将这条直线与凸多边形的两个交点的坐标分两行输出。你所求的直线必须与多边形有两个交点,且分多边形的两部分周长或面积相差都不能大于10^-3。
如果不存在,输出"impossible"(不含引号)。
Input示例
4
0 0
3 0
3 3
0 3
Output示例
1 0
2 3

解法:
任选多边形上一点,设周长为C,面积为S, p[x]表示顺时针沿着边走x长度的点,f(x)表示p[x],p[x + C / 2]以及沿途经过的顶点构成的多边形的面积 - S / 2。
则显然f(x) = -f(x + C / 2),由零点存在定理知[x, x + C / 2]中必有一解使函数值为0。二分找零点即可。
  1 #include <iostream>
  2 #include <fstream>
  3 #include <sstream>
  4 #include <cstdlib>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <string>
  8 #include <cstring>
  9 #include <algorithm>
 10 #include <queue>
 11 #include <stack>
 12 #include <vector>
 13 #include <set>
 14 #include <map>
 15 #include <list>
 16 #include <iomanip>
 17 #include <cctype>
 18 #include <cassert>
 19 #include <bitset>
 20 #include <ctime>
 21 
 22 using namespace std;
 23 
 24 #define pau system("pause")
 25 #define ll long long
 26 #define pii pair<int, int>
 27 #define pb push_back
 28 #define pli pair<ll, int>
 29 #define pil pair<int, ll>
 30 #define clr(a, x) memset(a, x, sizeof(a))
 31 
 32 const double pi = acos(-1.0);
 33 const int INF = 0x3f3f3f3f;
 34 const int MOD = 1e9 + 7;
 35 const double EPS = 1e-9;
 36 
 37 /*
 38 #include <ext/pb_ds/assoc_container.hpp>
 39 #include <ext/pb_ds/tree_policy.hpp>
 40 using namespace __gnu_pbds;
 41 #define TREE tree<pli, null_type, greater<pli>, rb_tree_tag, tree_order_statistics_node_update>
 42 TREE T;
 43 */
 44 
 45 struct Point {
 46     double x, y;
 47     Point () {}
 48     Point (double x, double y) : x(x), y(y) {}
 49     Point operator - (const Point &p) const {
 50         return Point(x - p.x, y - p.y);
 51     }
 52     double operator ^ (const Point &p) const {
 53         return x * p.y - y * p.x;
 54     }
 55     double len() {
 56         return sqrt(x * x + y * y);
 57     }
 58     bool operator == (const Point &p) const {
 59         return fabs(x - p.x) < EPS && fabs(y - p.y) < EPS;
 60     }
 61     void input() {
 62         scanf("%lf%lf", &x, &y);
 63     }
 64     void output() {
 65         printf("%.12f %.12f\n", x, y);
 66     }
 67 } p[40015], p1[40015], p2[40015];
 68 Point slice(Point p1, Point p2, double l) {
 69     double L = (p2 - p1).len();
 70     if (L < EPS) return p1;
 71     return Point(p1.x + (p2.x - p1.x) * l / L, p1.y + (p2.y - p1.y) * l / L);
 72 }
 73 double L[40015];
 74 double S(Point p[], int n) {
 75     double res = 0;
 76     for (int i = 0; i < n; ++i) {
 77         res += p[i] ^ p[(i + 1) % n];
 78     }
 79     return fabs(res);
 80 }
 81 int n;
 82 double totS;
 83 double cal(double x) {
 84     double sx = x, ex = x + L[n - 1] * 0.5;
 85     Point tp[40015];
 86     int index = 0;
 87     int id1 = upper_bound(L, L + n, sx) - L;
 88     int id2 = upper_bound(L, L + n, ex) - L;
 89     if (id1) sx -= L[id1 - 1];
 90     tp[index++] = slice(p[id1], p[(id1 + 1) % n], sx);
 91     for (int i = id1 + 1; i <= id2; ++i) {
 92         tp[index++] = p[i];
 93     }
 94     if (id2) ex -= L[id2 - 1];
 95     tp[index++] = slice(p[id2], p[(id2 + 1) % n], ex);
 96     return S(tp, index) - totS * 0.5;
 97 }
 98 Point get(double x) {
 99     int id = upper_bound(L, L + n, x) - L;
100     if (id) x -= L[id - 1];
101     return slice(p[id], p[(id + 1) % n], x);
102 }
103 int main() {
104     scanf("%d", &n);
105     for (int i = 0; i < n; ++i) {
106         p[i].input();
107     }
108     totS = 0;
109     for (int i = 0; i < n; ++i) {
110         L[i] = L[i - 1] + (p[(i + 1) % n] - p[i]).len();
111     }
112     double s = 0, e = L[n - 1] * 0.5, mi;
113     int f = cal(s) > 0;
114     for (int rep = 1; rep <= 70; ++rep) {
115         mi = (s + e) * 0.5;
116         double v = cal(mi);
117         if (fabs(v) < EPS) break;
118         if (f == (v > 0)) {
119             s = mi;
120         } else {
121             e = mi;
122         }
123     }
124     get(mi).output();
125     get(mi + L[n - 1] * 0.5).output();
126     return 0;
127 }
View Code

猜你喜欢

转载自www.cnblogs.com/BIGTOM/p/9814979.html
今日推荐