Description
Input
Output
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 8 const int MAXN = 110; 9 const double EPS = 1e-8; 10 const double PI = acos(-1.0);//3.14159265358979323846 11 const double INF = 1; 12 13 inline int sgn(double x) { 14 return (x > EPS) - (x < -EPS); 15 } 16 17 struct Point { 18 double x, y, ag; 19 Point() {} 20 Point(double x, double y): x(x), y(y) {} 21 void read() { 22 scanf("%lf%lf", &x, &y); 23 } 24 bool operator == (const Point &rhs) const { 25 return sgn(x - rhs.x) == 0 && sgn(y - rhs.y) == 0; 26 } 27 bool operator < (const Point &rhs) const { 28 if(y != rhs.y) return y < rhs.y; 29 return x < rhs.x; 30 } 31 Point operator + (const Point &rhs) const { 32 return Point(x + rhs.x, y + rhs.y); 33 } 34 Point operator - (const Point &rhs) const { 35 return Point(x - rhs.x, y - rhs.y); 36 } 37 Point operator * (const double &b) const { 38 return Point(x * b, y * b); 39 } 40 Point operator / (const double &b) const { 41 return Point(x / b, y / b); 42 } 43 double length() { 44 return sqrt(x * x + y * y); 45 } 46 Point unit() { 47 return *this / length(); 48 } 49 void print() { 50 printf("%.10f %.10f\n", x, y); 51 } 52 }; 53 typedef Point Vector; 54 55 double dist(const Point &a, const Point &b) { 56 return (a - b).length(); 57 } 58 59 double cross(const Point &a, const Point &b) { 60 return a.x * b.y - a.y * b.x; 61 } 62 //ret >= 0 means turn left 63 double cross(const Point &sp, const Point &ed, const Point &op) { 64 return sgn(cross(sp - op, ed - op)); 65 } 66 67 double area(const Point& a, const Point &b, const Point &c) { 68 return fabs(cross(a - c, b - c)) / 2; 69 } 70 //counter-clockwise 71 Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) { 72 Point t = p - o; 73 double x = t.x * cos(angle) - t.y * sin(angle); 74 double y = t.y * cos(angle) + t.x * sin(angle); 75 return Point(x, y) + o; 76 } 77 78 struct Seg { 79 Point st, ed; 80 double ag; 81 Seg() {} 82 Seg(Point st, Point ed): st(st), ed(ed) {} 83 void read() { 84 st.read(); ed.read(); 85 } 86 void makeAg() { 87 ag = atan2(ed.y - st.y, ed.x - st.x); 88 } 89 }; 90 typedef Seg Line; 91 92 //ax + by + c > 0 93 Line buildLine(double a, double b, double c) { 94 if(sgn(a) == 0 && sgn(b) == 0) return Line(Point(sgn(c) > 0 ? -1 : 1, INF), Point(0, INF)); 95 if(sgn(a) == 0) return Line(Point(sgn(b), -c/b), Point(0, -c/b)); 96 if(sgn(b) == 0) return Line(Point(-c/a, 0), Point(-c/a, sgn(a))); 97 if(b < 0) return Line(Point(0, -c/b), Point(1, -(a + c) / b)); 98 else return Line(Point(1, -(a + c) / b), Point(0, -c/b)); 99 } 100 101 void moveRight(Line &v, double r) { 102 double dx = v.ed.x - v.st.x, dy = v.ed.y - v.st.y; 103 dx = dx / dist(v.st, v.ed) * r; 104 dy = dy / dist(v.st, v.ed) * r; 105 v.st.x += dy; v.ed.x += dy; 106 v.st.y -= dx; v.ed.y -= dx; 107 } 108 109 bool isOnSeg(const Seg &s, const Point &p) { 110 return (p == s.st || p == s.ed) || 111 (((p.x - s.st.x) * (p.x - s.ed.x) < 0 || 112 (p.y - s.st.y) * (p.y - s.ed.y) < 0) && 113 sgn(cross(s.ed, p, s.st) == 0)); 114 } 115 116 bool isIntersected(const Point &s1, const Point &e1, const Point &s2, const Point &e2) { 117 return (max(s1.x, e1.x) >= min(s2.x, e2.x)) && 118 (max(s2.x, e2.x) >= min(s1.x, e1.x)) && 119 (max(s1.y, e1.y) >= min(s2.y, e2.y)) && 120 (max(s2.y, e2.y) >= min(s1.y, e1.y)) && 121 (cross(s2, e1, s1) * cross(e1, e2, s1) >= 0) && 122 (cross(s1, e2, s2) * cross(e2, e1, s2) >= 0); 123 } 124 125 bool isIntersected(const Seg &a, const Seg &b) { 126 return isIntersected(a.st, a.ed, b.st, b.ed); 127 } 128 129 bool isParallel(const Seg &a, const Seg &b) { 130 return sgn(cross(a.ed - a.st, b.ed - b.st)) == 0; 131 } 132 133 //return Ax + By + C =0 's A, B, C 134 void Coefficient(const Line &L, double &A, double &B, double &C) { 135 A = L.ed.y - L.st.y; 136 B = L.st.x - L.ed.x; 137 C = L.ed.x * L.st.y - L.st.x * L.ed.y; 138 } 139 //point of intersection 140 Point operator * (const Line &a, const Line &b) { 141 double A1, B1, C1; 142 double A2, B2, C2; 143 Coefficient(a, A1, B1, C1); 144 Coefficient(b, A2, B2, C2); 145 Point I; 146 I.x = - (B2 * C1 - B1 * C2) / (A1 * B2 - A2 * B1); 147 I.y = (A2 * C1 - A1 * C2) / (A1 * B2 - A2 * B1); 148 return I; 149 } 150 151 bool isEqual(const Line &a, const Line &b) { 152 double A1, B1, C1; 153 double A2, B2, C2; 154 Coefficient(a, A1, B1, C1); 155 Coefficient(b, A2, B2, C2); 156 return sgn(A1 * B2 - A2 * B1) == 0 && sgn(A1 * C2 - A2 * C1) == 0 && sgn(B1 * C2 - B2 * C1) == 0; 157 } 158 159 struct Poly { 160 int n; 161 Point p[MAXN];//p[n] = p[0] 162 void init(Point *pp, int nn) { 163 n = nn; 164 for(int i = 0; i < n; ++i) p[i] = pp[i]; 165 p[n] = p[0]; 166 } 167 double area() { 168 if(n < 3) return 0; 169 double s = p[0].y * (p[n - 1].x - p[1].x); 170 for(int i = 1; i < n; ++i) 171 s += p[i].y * (p[i - 1].x - p[i + 1].x); 172 return s / 2; 173 } 174 }; 175 176 void Graham_scan(Point *p, int n, int *stk, int &top) {//stk[0] = stk[top] 177 sort(p, p + n); 178 top = 1; 179 stk[0] = 0; stk[1] = 1; 180 for(int i = 2; i < n; ++i) { 181 while(top && cross(p[i], p[stk[top]], p[stk[top - 1]]) >= 0) --top; 182 stk[++top] = i; 183 } 184 int len = top; 185 stk[++top] = n - 2; 186 for(int i = n - 3; i >= 0; --i) { 187 while(top != len && cross(p[i], p[stk[top]], p[stk[top - 1]]) >= 0) --top; 188 stk[++top] = i; 189 } 190 } 191 //use for half_planes_cross 192 bool cmpAg(const Line &a, const Line &b) { 193 if(sgn(a.ag - b.ag) == 0) 194 return sgn(cross(b.ed, a.st, b.st)) < 0; 195 return a.ag < b.ag; 196 } 197 //clockwise, plane is on the right 198 bool half_planes_cross(Line *v, int vn, Poly &res, Line *deq) { 199 int i, n; 200 sort(v, v + vn, cmpAg); 201 for(i = n = 1; i < vn; ++i) { 202 if(sgn(v[i].ag - v[i-1].ag) == 0) continue; 203 v[n++] = v[i]; 204 } 205 int head = 0, tail = 1; 206 deq[0] = v[0], deq[1] = v[1]; 207 for(i = 2; i < n; ++i) { 208 if(isParallel(deq[tail - 1], deq[tail]) || isParallel(deq[head], deq[head + 1])) 209 return false; 210 while(head < tail && sgn(cross(v[i].ed, deq[tail - 1] * deq[tail], v[i].st)) > 0) 211 --tail; 212 while(head < tail && sgn(cross(v[i].ed, deq[head] * deq[head + 1], v[i].st)) > 0) 213 ++head; 214 deq[++tail] = v[i]; 215 } 216 while(head < tail && sgn(cross(deq[head].ed, deq[tail - 1] * deq[tail], deq[head].st)) > 0) 217 --tail; 218 while(head < tail && sgn(cross(deq[tail].ed, deq[head] * deq[head + 1], deq[tail].st)) > 0) 219 ++head; 220 if(tail <= head + 1) return false; 221 res.n = 0; 222 for(i = head; i < tail; ++i) 223 res.p[res.n++] = deq[i] * deq[i + 1]; 224 res.p[res.n++] = deq[head] * deq[tail]; 225 res.n = unique(res.p, res.p + res.n) - res.p; 226 res.p[res.n] = res.p[0]; 227 return true; 228 } 229 230 /*******************************************************************************************/ 231 232 Point p[MAXN], ans; 233 double f[15], sum[MAXN]; 234 double len, sqrt2 = sqrt(2); 235 int c, n, d; 236 237 void dfs(const Point &a, const Point &b, double len, int dep) { 238 if(dep == 0) { 239 ans = (b - a) * len / dist(a, b) + a; 240 } else { 241 for(int i = 1; i < n; ++i) { 242 if(sgn(sum[i] * dist(a, b) / dist(p[0], p[n - 1]) * f[dep] - len) < 0) continue; 243 double angle1 = atan2(p[n - 1].y - p[0].y, p[n - 1].x - p[0].x); 244 double angle2 = atan2(b.y - a.y, b.x - a.x); 245 Point o = rotate(p[i - 1], angle2 - angle1, p[0]); 246 o = (o - p[0]) * dist(a, b) / dist(p[0], p[n - 1]) + a; 247 Point t = rotate(p[i], angle2 - angle1, p[0]); 248 t = (t - p[0]) * dist(a, b) / dist(p[0], p[n - 1]) + a; 249 dfs(o, t, len - sum[i - 1] * f[dep] * dist(a, b) / dist(p[0], p[n - 1]), dep - 1); 250 return ; 251 } 252 } 253 } 254 255 void solve() { 256 sum[0] = 0; 257 for(int i = 1; i < n; ++i) sum[i] = sum[i - 1] + dist(p[i - 1], p[i]); 258 f[1] = 1; 259 double tmp = sum[n - 1] / dist(p[0], p[n - 1]); 260 for(int i = 2; i <= d; ++i) f[i] = f[i - 1] * tmp; 261 dfs(p[0], p[n - 1], len * sum[n - 1] * f[d], d); 262 } 263 264 int main() { 265 scanf("%d", &c); 266 while(c--) { 267 scanf("%d", &n); 268 for(int i = 0; i < n; ++i) p[i].read(); 269 scanf("%d%lf", &d, &len); 270 solve(); 271 printf("(%.10f,%.10f)\n", ans.x, ans.y); 272 } 273 }