-
質問の意味:
いくつかの線セグメントを与え、直線上にこれらの線セグメントの投影が共通点を持つように直線があるかどうかを尋ねます -
アイデア
偉大な神のブログを読んだ後、問題はすべての線セグメントと交差する直線mがあるかどうかに変換でき、mに垂直な直線lが目的の直線であることに気付きました。
2つの線セグメントの端点の2行2列の組み合わせ(2つの端点は異なる線セグメントから取得されます)を直線mの線セグメントとして列挙できます(実際には、指定された線セグメントが制限されているため、直線mがある場合は次のようになります。与えられたすべてのラインセグメントと交差するラインのセグメントを取ります)、なぜ2つの異なるラインセグメントの2つのエンドポイントによって形成されるラインを列挙するのですか?この線が存在すると仮定すると、特定の線セグメントの終点に到達するまで線を常に平行に移動し、終点を軸として線を回転させることができます。これにより、別の線セグメントの終点まで確実に回転します。それが証明され、必要なラインmから取られた条件を満たす(与えられたラインセグメントと交差する)ラインセグメントです。2つのラインセグメントの交差を判断する方法は?私たちは知っている×BA \回bは、a××b = | a | | b | sinθ\ sin \ thetaなしθ。2つのベクトル間の角度が108°より大きい場合、交差積の積は負になります(a×b≠b×aa \ times b \ not = b \ times aa××b=b××a、絶対値は同じですが、正と負は反対です)。
ラインセグメントabとcdが交差する場合、ca⃗×cb⃗\ vec {ca} \ times \ vec {cb}があります。c a××c b和DA⃗×DB⃗\ VEC {DA} \回\ VEC {DB}d a××d b異なる符号とda⃗×ca⃗\ vec {da} \ times \ vec {ca}d a××c aそしてdb⃗×cb⃗\ vec {db} \ times \ vec {cb}d b××c bまた違う
-
コード
#pragma GCC optimize(2)
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
typedef unsigned long ul;
typedef unsigned long long ull;
#define pi acos(-1.0)
#define e exp(1.0)
#define pb push_back
#define mk make_pair
#define fir first
#define sec second
#define scf scanf
#define prf printf
typedef pair<ll,ll> pa;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int MAX_N=116;
const double eps=1e-8;
int N,T;
struct node{
double x,y;
}seg_l[MAX_N],seg_r[MAX_N];
double gao(node a,node b,node tmp){
double x1,x2,y1,y2;
x1=a.x-tmp.x;
y1=a.y-tmp.y;
x2=b.x-tmp.x;
y2=b.y-tmp.y;
return x1*y2-x2*y1;
}
bool do_(node a,node b){
int i,j;
if(fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps)
return 0;
for(i=1;i<=N;i++){
if(gao(a,b,seg_l[i])*gao(a,b,seg_r[i])>eps)
return 0;
}
return 1;
}
int main()
{
// freopen(".../.txt","w",stdout);
// freopen(".../.txt","r",stdin);
ios::sync_with_stdio(false);
cin>>T;
int i,j;
while(T--){
cin>>N;
for(i=1;i<=N;i++){
cin>>seg_l[i].x>>seg_l[i].y>>seg_r[i].x>>seg_r[i].y;
}
if(N==1){
cout<<"Yes!"<<endl;
continue;
}
bool flag=0;
for(i=1;i<=N;i++){
for(j=i+1;j<=N;j++){
if(do_(seg_l[i],seg_l[j]))
flag=1;
else if(do_(seg_l[i],seg_r[j]))
flag=1;
else if(do_(seg_r[i],seg_l[j]))
flag=1;
else if(do_(seg_r[i],seg_r[j]))
flag=1;
// if(flag)
// break;
}
if(flag)
break;
}
if(flag)
cout<<"Yes!"<<endl;
else
cout<<"No!"<<endl;
}
return 0;
}