件名の説明:
ソリューション:
計算幾何学、非常に多くのピット。
まず、すべてのセグメント、すなわち$はい$通る直線があることは明らかです。
任意の2つのエンドポイントを列挙考えてみましょう。
注また、セグメント上の同じを列挙!
$ EPS = 1E-8 $ことに注意してください!
2つの点が言い渡さ一致しないことに注意してください!
コード:
#include <cmath> の#include <cstdioを> する#include <CStringの> する#include <アルゴリズム> 使用して 名前空間STDを、 CONSTの INT N = 150 。 constの ダブル EPS = 1E- 8 ; 構造体のポイント { ダブルX、Y。 ポイント(){} 点(ダブル X、ダブルY):X(X)、Y(Y){} ポイント演算子 - (CONSTポイント&A)のconst { 戻り点(xa.x、Y- AY)を;} ダブル 演算子 ^(CONSTポイント&A)のconst { リターンのx *のAY-Y * AX;} }。 typedefのポイント・ベクトル。 構造体のライン { 点p; ベクトルv。 ライン(){} 線(点P、ベクトルv):P(P)、V(V){} }。 int型のn; 点S [N] [ 2 ]。 INT DCMP(ダブルX) { 場合(ファブ(X)<EPS)戻り 0 ; 返すのx> 0?1: - 1 。 } ブール差分(ラインL、A点、B点) { 戻り DCMP(LV ^(al.p))* DCMP(LV ^(bl.p))<= 0 。 } int型のチェック(A点、B点) { 場合(DCMP(AX-BX)&& DCMP(AY-によって)!)戻り 0 ; 線l =ライン(B- A)。 用(int型 I = 1を iが++; iが<= N ) であれば(!差分(L、S [i]が[ 0 ]、S [i]を[ 1 ]))戻り 0 ; リターン 1 ; } ボイドワーク() { scanf関数(" %dの"&N) のための(int型 I = 1を iが<= N; iが++ ) のscanf(" %LF%LF%LF%LF 」、&S [i]が[ 0 ] .X、&S [i]が[ 0 ] .Y、&S [i]は[ 1 ] .X、&S [i]は[ 1 ] .Y); int型の FG = 0 ; のため(int型 I = 1!FG && I <= N; I ++)のための(INT J = ;!FG && J <= N; J ++ ) 場合(チェック(S [i]が[ 0 ]、S [j] [ 0 ])||チェック(S [i]が[ 0 ]、S [j]を[ 1])||チェック(S [i]が[ 1 ]、S [j] [ 0 ])||チェック(S [i]が[ 1 ]、S [j]を[ 1 ]))FG = 1 。 プット(FG?" はい!":" いいえ!" ); } int型のT。 INT メイン() { scanf関数(" %のD "、&T)。 一方、(T-- )ワーク(); リターン 0 ; }