#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; static const double EPS_SMALL = 1e-8; static const double EPS_LARGE = 1e-5; static const double EPS = EPS_SMALL; static const double PI = 4.0 * atan(1.0); static const double PI2 = 8.0 * atan(1.0); typedef long long ll; typedef complex P; //http://www.prefield.com/algorithm/geometry/geometry.html namespace std { bool operator < (const P& a, const P& b) { return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b); } } double cross(const P& a, const P& b) { return imag(conj(a)*b); } double dot(const P& a, const P& b) { return real(conj(a)*b); } struct L { P a, b; L() {} L(const P &a, const P &b) : a(a), b(b){} P& operator[](int i) { return i ? b : a; } const P& operator[](int i) const { return i ? b : a; } }; //http://www.prefield.com/algorithm/geometry/ccw.html int ccw(P a, P b, P c) { b -= a; c -= a; if (cross(b, c) > 0) return +1; // counter clockwise if (cross(b, c) < 0) return -1; // clockwise if (dot(b, c) < 0) return +2; // c--a--b on line if (norm(b) < norm(c)) return -2; // a--b--c on line return 0; } //http://www.prefield.com/algorithm/geometry/intersection.html bool intersectLL(const L &l, const L &m) { return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel abs(cross(l[1]-l[0], m[0]-l[0])) < EPS; // same line } bool intersectLS(const L &l, const L &s) { return cross(l[1]-l[0], s[0]-l[0])* // s[0] is left of l cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l } bool intersectLP(const L &l, const P &p) { return abs(cross(l[1]-p, l[0]-p)) < EPS; } bool intersectSS(const L &s, const L &t) { return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 && ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0; } bool intersectSP(const L &s, const P &p) { return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality } //http://www.prefield.com/algorithm/geometry/distance.html P projection(const L &l, const P &p) { double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]); return l[0] + t*(l[0]-l[1]); } P reflection(const L &l, const P &p) { return p + 2.0 * (projection(l, p) - p); } double distanceLP(const L &l, const P &p) { return abs(p - projection(l, p)); } double distanceLL(const L &l, const L &m) { return intersectLL(l, m) ? 0 : distanceLP(l, m[0]); } double distanceLS(const L &l, const L &s) { if (intersectLS(l, s)) return 0; return min(distanceLP(l, s[0]), distanceLP(l, s[1])); } double distanceSP(const L &s, const P &p) { const P r = projection(s, p); if (intersectSP(s, r)) return abs(r - p); return min(abs(s[0] - p), abs(s[1] - p)); } double distanceSS(const L &s, const L &t) { if (intersectSS(s, t)) return 0; return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])), min(distanceSP(t, s[0]), distanceSP(t, s[1]))); } P crosspoint(const L &l, const L &m) { double A = cross(l[1] - l[0], m[1] - m[0]); double B = cross(l[1] - l[0], l[1] - m[0]); if (abs(A) < EPS && abs(B) < EPS) return m[0]; // same line if (abs(A) < EPS) assert(false); // !!!PRECONDITION NOT SATISFIED!!! return m[0] + B / A * (m[1] - m[0]); } //ここから自分のコード //#define METAPOST #ifdef METAPOST static FILE* file = NULL; static const double offsetX = 10.0; static const double offsetY = 10.0; static const P offset(offsetX, offsetY); static const double scale = 0.75; void drawLine(P a, P b) { a += offset; b += offset; a *= scale; b *= scale; fprintf(file, "\tdraw (%lf, %lf) -- (%lf, %lf);\n", a.real(), a.imag(), b.real(), b.imag()); } void drawLine(L l) { P dir = l[1] - l[0]; dir /= abs(dir); dir *= 1000; l[0] -= dir; l[1] += dir; drawLine(l[0], l[1]); } void drawPoint(P a) { a += offset; a *= scale; fprintf(file, "\tdraw (%lf, %lf) withpen pencircle scaled 2bp;\n", a.real(), a.imag()); } void drawCircle(P c, double r) { c += offset; c *= scale; r *= scale; fprintf(file, "\tdraw fullcircle scaled %lf shifted (%lf, %lf);\n", r, c.real(), c.imag()); } #endif //直線lからr離れた直線を2本生成する void createLaserSides(const L& l, double r, L out[2]) { const P dir = l[0] - l[1]; P h(-dir.imag(), dir.real()); h *= r / abs(h); out[0] = l; out[0][0] += h; out[0][1] += h; out[1] = l; out[1][0] -= h; out[1][1] -= h; } bool isParallel(const L& l0, const L& l1) { const P a = l0[0] - l0[1]; const P b = l1[0] - l1[1]; return abs(cross(a, b)) < EPS_SMALL; } //安地の候補を列挙する //候補はl0からr0+r離れた直線とl1からr1+r離れた直線上 bool createSafePositionCandidates(const L& l0, double r0, const L& l1, double r1, double r, P out[4]) { if (isParallel(l0, l1)) { return false; } L l[2][2]; createLaserSides(l0, r0 + r + EPS_LARGE, l[0]); createLaserSides(l1, r1 + r + EPS_LARGE, l[1]); int index = 0; for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { out[index++] = crosspoint(l[0][i], l[1][j]); } } return true; } bool isSafe(const P& p, double r, const vector& lasers, const vector& radiuses, int W, int H) { if (p.real() < -EPS || W + EPS < p.real() || p.imag() < -EPS || H + EPS < p.imag()) { return false; } const int n = lasers.size(); for (int i = 0; i < n; ++i) { const L& laser = lasers[i]; const double radius = radiuses[i]; if (distanceLP(laser, p) < r + radius + EPS_SMALL) { return false; } } return true; } bool check(const vector& lasers, const vector& radiuses, double r, int W, int H) { const int n = lasers.size(); for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { P p[4]; if (!createSafePositionCandidates(lasers[i], radiuses[i], lasers[j], radiuses[j], r, p)) { continue; } for (int k = 0; k < 4; ++k) { #ifdef METAPOST drawPoint(p[k]); #endif if (isSafe(p[k], r, lasers, radiuses, W, H)) { #ifdef METAPOST drawCircle(p[k], r); #endif return true; } } } } return false; } int main(int argc, char* argv[]) { #ifdef METAPOST file = fopen("metapost.mp", "wt"); fprintf(file, "beginfig(%s)\n", argv[1]); #endif for (int W, H, N, R; cin >> W >> H >> N >> R && (W || H || N || R);) { vector lasers; vector radiuses(4); lasers.push_back(L(P(0, 0), P(W, 0))); lasers.push_back(L(P(0, 0), P(0, H))); lasers.push_back(L(P(0, H), P(W, H))); lasers.push_back(L(P(W, 0), P(W, H))); #ifdef METAPOST for (int i = 0; i < 4; ++i) { drawLine(lasers[i][0], lasers[i][1]); } #endif for (int i = 0; i < N; ++i) { int x0, y0, x1, y1, r; cin >> x0 >> y0 >> x1 >> y1 >> r; lasers.push_back(L(P(x0, y0), P(x1, y1))); radiuses.push_back(r); #ifdef METAPOST L out[2]; createLaserSides(lasers.back(), radiuses.back(), out); drawLine(out[0]); drawLine(out[1]); #endif } if (check(lasers, radiuses, R, W, H)) { cout << "Yes" << endl; } else { cout << "No" << endl; } } #ifdef METAPOST fprintf(file, "endfig;\nend.\n"); fclose(file); file = NULL; #endif }