poj 1092 Farmland (Geometry)
怎么最近做几何题都这么蛋疼,提交C++过不了交G++就过了。据我估计,原因是用了atan2这个函数,或者是其他一些函数造成了精度的影响。不管怎样,这题最后还是过了~
解释一下题意,题目的意思是,给出一些边和点,要求找到简单多边形,也就是没有重复的点的多边形,而且多边形里面不能有其他的点。
于是,还是之前的做法,对于每一条边作为起始边,从这条边出发,找最往左的一个点,然后移动到那里。不停这样的模拟,直到走回起始位置,就计算多边形是由多少条边构成的。如果满足就对计数器加一,最后输出结果即可。
最早通过的版本的写法是可以不用检查有没有点在多边形里面的:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <vector> 7 #include <map> 8 9 using namespace std; 10 11 const int N = 222; 12 struct Point { 13 int x, y; 14 Point() {} 15 Point(int x, int y) : x(x), y(y) {} 16 Point operator + (Point a) { return Point(x + a.x, y + a.y);} 17 Point operator - (Point a) { return Point(x - a.x, y - a.y);} 18 } pt[N]; 19 20 typedef pair<int, int> PII; 21 typedef vector<Point> VPT; 22 typedef vector<int> VI; 23 24 inline double angle(Point x) { return atan2((double) x.y, (double) x.x);} 25 inline int cross(Point x, Point y) { return x.x * y.y - x.y * y.x;} 26 27 VI rel[N]; 28 Point ori; 29 map<int, int> pid; 30 map<int, int> nx[N]; 31 bool vis[N][N], vs[N]; 32 int rec[N]; 33 34 inline bool cmp(int a, int b) { return angle(pt[a] - ori) < angle(pt[b] - ori);} 35 double area() { 36 double ret = 0.0; 37 rec[rec[0] + 1] = rec[1]; 38 for (int i = 1; i <= rec[0]; i++) ret += cross(pt[rec[i]], pt[rec[i + 1]]); 39 return ret / 2.0; 40 } 41 42 int main() { 43 // freopen("in", "r", stdin); 44 // freopen("out", "w", stdout); 45 int T, n, k, x, id; 46 scanf("%d", &T); 47 while (T-- && ~scanf("%d", &n)) { 48 pid.clear(); 49 for (int i = 0; i < n; i++) { 50 scanf("%d", &id); 51 if (pid.find(id) == pid.end()) pid[id] = pid.size(); 52 rel[pid[id]].clear(); 53 nx[pid[id]].clear(); 54 scanf("%d%d", &pt[pid[id]].x, &pt[pid[id]].y); 55 scanf("%d", &k); 56 while (k--) { 57 scanf("%d", &x); 58 if (pid.find(x) == pid.end()) pid[x] = pid.size(); 59 rel[pid[id]].push_back(pid[x]); 60 } 61 } 62 // for (int i = 1; i <= n; i++) cout << i << ' ' << pid[i] << endl; 63 scanf("%d", &k); 64 for (int i = 1, sz; i <= n; i++) { 65 ori = pt[i]; 66 sort(rel[i].begin(), rel[i].end(), cmp); 67 sz = rel[i].size(); 68 if (sz <= 1) continue; 69 rel[i].push_back(rel[i][0]); 70 for (int j = 0; j < sz; j++) nx[rel[i][j + 1]][i] = rel[i][j]; 71 rel[i].pop_back(); 72 } 73 memset(vis, 0, sizeof(vis)); 74 int cnt = 0; 75 for (int i = 1, len, t; i <= n; i++) { 76 for (int j = 0, sz = rel[i].size(); j < sz; j++) { 77 memset(vs, 0, sizeof(vs)); 78 rec[0] = 0; 79 int ls = i, cr = rel[i][j]; 80 rec[++rec[0]] = ls; 81 bool ok = true; 82 vs[cr] = true; 83 if (vis[ls][cr]) continue; 84 len = 1; 85 // cout << "start " << i << ' '; 86 while (cr != i) { 87 rec[++rec[0]] = cr; 88 // cout << cr << ' '; 89 t = cr; 90 cr = nx[ls][cr]; 91 if (cr <= 0) { 92 len = -1; 93 break; 94 } 95 if (vs[cr]) ok = false; 96 vs[cr] = true; 97 ls = t; 98 vis[ls][cr] = true; 99 len++; 100 } 101 // cout << "~~" << len << endl; 102 if (ok && len == k && vs[nx[ls][cr]] && area() > 0.0) cnt++; 103 } 104 } 105 printf("%d\n", cnt); 106 } 107 return 0; 108 }
因为开始的时候wa太多次了,所以我的代码对标号重标号了。
然后不停的改啊改,最后改到把检查点在多边形内的操作也加上去了~
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <cmath> 6 #include <vector> 7 #include <map> 8 9 using namespace std; 10 11 const int N = 222; 12 struct Point { 13 int x, y; 14 Point() {} 15 Point(int x, int y) : x(x), y(y) {} 16 Point operator + (Point a) { return Point(x + a.x, y + a.y);} 17 Point operator - (Point a) { return Point(x - a.x, y - a.y);} 18 } pt[N]; 19 20 typedef pair<int, int> PII; 21 typedef vector<Point> VPT; 22 typedef vector<int> VI; 23 24 inline double angle(Point x) { return atan2((double) x.y, (double) x.x);} 25 inline int cross(Point x, Point y) { return x.x * y.y - x.y * y.x;} 26 27 VI rel[N]; 28 Point ori; 29 map<int, int> pid; 30 map<int, int> nx[N]; 31 bool vis[N][N], vs[N]; 32 int rec[N]; 33 34 inline bool cmp(int a, int b) { return angle(pt[a] - ori) < angle(pt[b] - ori);} 35 double area() { 36 double ret = 0.0; 37 rec[rec[0] + 1] = rec[1]; 38 for (int i = 1; i <= rec[0]; i++) ret += cross(pt[rec[i]], pt[rec[i + 1]]); 39 return ret / 2.0; 40 } 41 42 bool test(int p) { 43 int sz = rec[0], wn = 0; 44 rec[sz + 1] = rec[1]; 45 for (int i = 1; i <= sz; i++) { 46 if (pt[p].x == pt[rec[i]].x && pt[p].y == pt[rec[i]].y) return false; 47 int k = cross(pt[rec[i + 1]] - pt[rec[i]], pt[p] - pt[rec[i]]); 48 int d1 = pt[rec[i]].y - pt[p].y; 49 int d2 = pt[rec[i + 1]].y - pt[p].y; 50 if (k > 0 && d1 <= 0 && d2 > 0) wn++; 51 if (k < 0 && d2 <= 0 && d1 > 0) wn--; 52 } 53 return wn != 0; 54 } 55 56 bool check() { 57 // for (int i = 1; i <= rec[0]; i++) cout << rec[i] << ' '; cout << endl; 58 for (int i = 1, sz = pid.size(); i <= sz; i++) { 59 if (test(i)) return false; 60 } 61 return true; 62 } 63 64 int main() { 65 // freopen("in", "r", stdin); 66 // freopen("out", "w", stdout); 67 int T, n, k, x, id; 68 scanf("%d", &T); 69 while (T-- && ~scanf("%d", &n)) { 70 pid.clear(); 71 for (int i = 0; i < n; i++) { 72 scanf("%d", &id); 73 if (pid.find(id) == pid.end()) pid[id] = pid.size(); 74 rel[pid[id]].clear(); 75 nx[pid[id]].clear(); 76 scanf("%d%d", &pt[pid[id]].x, &pt[pid[id]].y); 77 scanf("%d", &k); 78 while (k--) { 79 scanf("%d", &x); 80 if (pid.find(x) == pid.end()) pid[x] = pid.size(); 81 rel[pid[id]].push_back(pid[x]); 82 } 83 } 84 // for (int i = 1; i <= n; i++) cout << i << ' ' << pid[i] << endl; 85 scanf("%d", &k); 86 if (k < 3) { puts("0"); continue;} 87 for (int i = 1, sz; i <= n; i++) { 88 ori = pt[i]; 89 sort(rel[i].begin(), rel[i].end(), cmp); 90 sz = rel[i].size(); 91 if (sz <= 1) continue; 92 rel[i].push_back(rel[i][0]); 93 for (int j = 0; j < sz; j++) nx[rel[i][j + 1]][i] = rel[i][j]; 94 rel[i].pop_back(); 95 } 96 memset(vis, 0, sizeof(vis)); 97 int cnt = 0; 98 for (int i = 1, len, t; i <= n; i++) { 99 for (int j = 0, sz = rel[i].size(); j < sz; j++) { 100 rec[0] = 0; 101 int ls = i, cr = rel[i][j]; 102 if (vis[ls][cr]) continue; 103 vis[ls][cr] = true; 104 bool ok = true; 105 memset(vs, 0, sizeof(vs)); 106 len = 1; 107 // cout << "start " << i << ' '; 108 while (nx[ls][cr]) { 109 rec[++rec[0]] = cr; 110 // cout << cr << ' '; 111 t = cr; 112 cr = nx[ls][cr]; 113 if (cr <= 0) { 114 len = -1; 115 break; 116 } 117 if (vs[cr]) ok = false; 118 vs[cr] = true; 119 ls = t; 120 if (vis[ls][cr]) break; 121 vis[ls][cr] = true; 122 len++; 123 } 124 // cout << "~~" << len << endl; 125 if (ok && len == k && ls == i && area() >= 1e-5 && check()) cnt++; 126 } 127 } 128 printf("%d\n", cnt); 129 } 130 return 0; 131 }
——written by Lyon