Description
Input
Output
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <iostream> 5 #include <cmath> 6 #include <vector> 7 #include <map> 8 using namespace std; 9 typedef long long LL; 10 typedef pair<int, int> PII; 11 12 const double PI = acos(-1.0); 13 const double EPS = 1e-8; 14 15 inline int sgn(double x) { 16 return (x > EPS) - (x < -EPS); 17 } 18 19 struct Point { 20 double x, y; 21 Point() {} 22 Point(double x, double y): x(x), y(y) {} 23 void read() { 24 scanf("%lf%lf", &x, &y); 25 } 26 Point operator + (const Point &rhs) const { 27 return Point(x + rhs.x, y + rhs.y); 28 } 29 Point operator - (const Point &rhs) const { 30 return Point(x - rhs.x, y - rhs.y); 31 } 32 Point operator * (double t) const { 33 return Point(x * t, y * t); 34 } 35 double length() const { 36 return sqrt(x * x + y * y); 37 } 38 Point unit() const { 39 double l = length(); 40 return Point(x / l, y / l); 41 } 42 }; 43 44 double dist(const Point &p1, const Point &p2) { 45 return (p1 - p2).length(); 46 } 47 48 Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) { 49 Point t = p - o; 50 double x = t.x * cos(angle) - t.y * sin(angle); 51 double y = t.y * cos(angle) + t.x * sin(angle); 52 return Point(x, y) + o; 53 } 54 55 double cross(const Point &a, const Point &b) { 56 return a.x * b.y - a.y * b.x; 57 } 58 59 double cross(const Point &sp, const Point &ep, const Point &op) { 60 return cross(sp - op, ep - op); 61 } 62 63 struct Seg { 64 Point st, ed; 65 Seg() {} 66 Seg(Point st, Point ed): st(st), ed(ed) {} 67 void read() { 68 st.read(); ed.read(); 69 } 70 }; 71 typedef Seg Line; 72 //return Ax + By + C =0 's A, B, C 73 void Coefficient(const Line &L, double &A, double &B, double &C) { 74 A = L.ed.y - L.st.y; 75 B = L.st.x - L.ed.x; 76 C = L.ed.x * L.st.y - L.st.x * L.ed.y; 77 } 78 //point of intersection 79 Point operator * (const Line &a, const Line &b) { 80 double A1, B1, C1; 81 double A2, B2, C2; 82 Coefficient(a, A1, B1, C1); 83 Coefficient(b, A2, B2, C2); 84 Point I; 85 I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1); 86 I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1); 87 return I; 88 } 89 90 double Point_to_Line(const Point &p, const Line &L) { 91 return fabs(cross(p, L.st, L.ed)/dist(L.st, L.ed)); 92 } 93 94 Point reflection(const Point &p, const Line &l) { 95 Point t = rotate(l.ed - l.st, -PI / 2); 96 return p + t.unit() * (2 * Point_to_Line(p, l)); 97 } 98 99 vector<Point> p_vec, p_buf; 100 101 struct Poly { 102 vector<int> id; 103 void add(int i) { 104 id.push_back(i); 105 } 106 Point& operator [] (int i) const { 107 return p_vec[id[i]]; 108 } 109 }; 110 111 vector<Poly> pol_vec, pol_buf; 112 map<PII, int> edge_map; 113 114 Point paper[] = {Point(0, 0), Point(0, 1), Point(1, 1), Point(1, 0)}; 115 116 void reflection(const Poly &pol, const Line &l) { 117 for(int i = 0; i < int(pol.id.size()); ++i) 118 if(pol.id[i] < int(p_buf.size())) p_buf[pol.id[i]] = reflection(pol[i], l); 119 } 120 121 int intersection(int id1, int id2, const Point &p1, const Point &p2) { 122 map<PII, int>::iterator it = edge_map.find(make_pair(id1, id2)); 123 if(it == edge_map.end()) { 124 p_vec.push_back(Line(p_vec[id1], p_vec[id2]) * Line(p1, p2)); 125 edge_map[make_pair(id1, id2)] = edge_map[make_pair(id1, id2)] = p_vec.size() - 1; 126 return p_vec.size() - 1; 127 } else return it->second; 128 } 129 130 void fold(const Point &p1, const Point &p2, const Poly &pol) { 131 Poly res1, res2; 132 int last_s = sgn(cross(p1, pol[0], p2)); 133 for(int i = 1; i < int(pol.id.size()); ++i) { 134 int now_s = sgn(cross(p1, pol[i], p2)); 135 if(now_s == 0) { 136 res1.add(pol.id[i]); 137 res2.add(pol.id[i]); 138 } else if(now_s < 0) { 139 if(last_s > 0) { 140 int k = intersection(pol.id[i - 1], pol.id[i], p1, p2); 141 res1.add(k); 142 res2.add(k); 143 } 144 res1.add(pol.id[i]); 145 } else if(now_s > 0) { 146 if(last_s < 0) { 147 int k = intersection(pol.id[i - 1], pol.id[i], p1, p2); 148 res1.add(k); 149 res2.add(k); 150 } 151 res2.add(pol.id[i]); 152 } 153 last_s = now_s; 154 } 155 if(res1.id.size() > 2) { 156 res1.add(res1.id[0]); 157 reflection(res1, Line(p1, p2)); 158 reverse(res1.id.begin(), res1.id.end()); 159 pol_buf.push_back(res1); 160 } 161 if(res2.id.size() > 2) { 162 res2.add(res2.id[0]); 163 pol_buf.push_back(res2); 164 } 165 } 166 167 void fold(const Point &p1, const Point &p2) { 168 p_buf = p_vec; 169 edge_map.clear(); 170 pol_buf.clear(); 171 for(int i = 0; i < int(pol_vec.size()); ++i) 172 fold(p1, p2, pol_vec[i]); 173 pol_vec = pol_buf; 174 for(int i = 0; i < int(p_buf.size()); ++i) 175 p_vec[i] = p_buf[i]; 176 } 177 178 void dfs(vector<bool> &vis, int id, const Line &l) { 179 vis[id] = true; 180 Poly &pol = pol_vec[id]; 181 for(int i = 0; i < int(pol.id.size() - 1); ++i) { 182 if(sgn(cross(l.ed, pol[i], l.st)) == 0 && sgn(cross(l.ed, pol[i + 1], l.st)) == 0) continue; 183 int id1 = pol.id[i], id2 = pol.id[i + 1]; 184 for(int j = 0; j < int(pol_vec.size()); ++j) { 185 if(vis[j]) continue; 186 for(int k = 0; k < int(pol_vec[j].id.size() - 1); ++k) { 187 if(pol_vec[j].id[k] == id1 && pol_vec[j].id[k + 1] == id2) { 188 dfs(vis, j, l); 189 break; 190 } 191 } 192 } 193 } 194 } 195 196 int cut(const Line &l) { 197 int ret = 0; 198 vector<bool> vis(p_vec.size()); 199 for(int i = 0; i < int(pol_vec.size()); ++i) { 200 if(!vis[i]) { 201 dfs(vis, i, l); 202 ++ret; 203 } 204 } 205 return ret; 206 } 207 208 int main() { 209 int T; 210 scanf("%d", &T); 211 Poly init_pol; 212 for(int i = 0; i <= 4; ++i) init_pol.add(i & 3); 213 while(T--) { 214 int n; 215 scanf("%d", &n); 216 p_vec.clear(); 217 pol_vec.clear(); 218 for(int i = 0; i < 4; ++i) p_vec.push_back(paper[i]); 219 for(int i = 0; i <= 4; ++i) pol_vec.push_back(init_pol); 220 Point p1, p2; 221 for(int i = 0; i <= n; ++i) { 222 p1.read(), p2.read(); 223 fold(p1, p2); 224 } 225 printf("%d\n", cut(Line(p1, p2))); 226 } 227 }