// 2009模擬地区予選 E : Safe Area #include #include #include #include #include using namespace std; typedef complex P; struct L { P p, q; L(P p, P q) : p(p), q(q) {} }; const double EPS = 1e-8; double cross(P a, P b){ return imag(conj(a)*b); } double rot(P a, P b){ return arg(conj(a)*b); } P ssCrosspoint(L a, L b){ double A = cross(a.q-a.p, b.q-b.p); double B = cross(a.q-a.p, a.q-b.p); return b.p + B/A*(b.q-b.p); } double distLP(L l, P p){ return abs(cross(l.q-l.p,p-l.p))/abs(l.q-l.p); } // 直線a, bの両方から距離rの位置にある点をvpに加える void getPoint(vector

&vp, L a, L b, double r){ // 直線が交差しない if(abs(imag((a.q-a.p)/(b.q-b.p))) < EPS) return ; P c = ssCrosspoint(a, b); P dirA = (a.q-a.p)/abs(a.q-a.p); // aの向きベクトル P dirB = (b.q-b.p)/abs(b.q-b.p); // bの向きベクトル P dirC = (dirA+dirB)/abs(dirA+dirB); // 角2等分線の向きベクトル P dirD = dirC*P(0,1); // もう一方の2等分線の向きベクトル double rad = abs(rot(dirA, dirC)); vp.push_back(c+dirC*r/sin(rad)); vp.push_back(c-dirC*r/sin(rad)); vp.push_back(c+dirD*r/cos(rad)); vp.push_back(c-dirD*r/cos(rad)); } // 2つのレーザーa, bに対するギリギリの安置をvpに加える void getSafepoint(vector

&vp, pair a, pair b, double w, double h, double r){ vector

tmp; L l = a.first, m = b.first; P dirA = a.second*(l.q-l.p)/abs(l.q-l.p)*P(0,1); P dirB = b.second*(m.q-m.p)/abs(m.q-m.p)*P(0,1); // a, bの中心線を厚さの分だけ平行移動した直線を考える getPoint(tmp, L(l.p+dirA,l.q+dirA), L(m.p+dirB,m.q+dirB), r); getPoint(tmp, L(l.p+dirA,l.q+dirA), L(m.p-dirB,m.q-dirB), r); getPoint(tmp, L(l.p-dirA,l.q-dirA), L(m.p+dirB,m.q+dirB), r); getPoint(tmp, L(l.p-dirA,l.q-dirA), L(m.p-dirB,m.q-dirB), r); for(int i=0;i> w >> h >> n >> r, w){ vector< pair > laser; // 処理を簡単にするため画面周囲を厚さ1のレーザーに囲まれていると考える laser.push_back(make_pair(L(P(0, -1),P(w, -1)),1)); laser.push_back(make_pair(L(P(0,h+1),P(w,h+1)),1)); laser.push_back(make_pair(L(P( -1,0),P( -1,h)),1)); laser.push_back(make_pair(L(P(w+1,0),P(w+1,h)),1)); int x1, y1, x2, y2, t; for(int i=0;i> x1 >> y1 >> x2 >> y2 >> t; laser.push_back(make_pair(L(P(x1,y1),P(x2,y2)),t)); } vector

vp; // 安置の候補を調べる for(int i=0;i