1. 程式人生 > >51NOD - 1976 多邊形劃分

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