poj 1092 Farmland (Geometry)

1092 -- Farmland

  怎么最近做几何题都这么蛋疼,提交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
", cnt);
106     }
107     return 0;
108 }
View Code

  因为开始的时候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
", cnt);
129     }
130     return 0;
131 }
View Code

——written by Lyon

原文地址:https://www.cnblogs.com/LyonLys/p/poj_1092_Lyon.html