【题解】POJ3304Segments-计算几何
Segments
https://ac.nowcoder.com/acm/problem/107901
POJ3304
大致题意
给定个线段,求是否存在一条直线,所有的线段在该直线上的投影都有一个公共点。
思路
题目可以转化为,是否存在一条直线可以穿过所有的线段。我们可以将所有的线段的两个端点全部存在一个数组里,任取两个不同的点构成直线,判断这条直线是否穿过所有线段。如果有一条这样的线段存在就输出Yes!,否则输出No!直线穿过线段可以使用向量和点的有向面积来判断。
代码
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
typedef pair<int,int> PII;
typedef pair<LL,LL> PLL;
typedef pair<double,double> PDD;
#define fi first
#define se second
#define mp make_pair
#define IOS ios::sync_with_stdio(false),cin.tie(0)
const int N = 200 + 10;
const int MOD = 998244353;
const int INF = 0x3f3f3f3f;
const double eps = 1e-8;
PDD q[N],a[N],b[N];
int n;
int cmp(double x,double y){
if (fabs(x - y) < eps) return 0;
if (x < y) return -1;
return 1;
}
int sign(double x){
if (fabs(x) < eps) return 0;
if (x > 0) return 1;
return -1;
}
double cross(double x1,double y1,double x2,double y2){
return (x1 * y2 - x2 * y1);
}
double area(PDD x,PDD y,PDD z){
return cross(y.fi - x.fi,y.se - x.se,z.fi - x.fi,z.se - x.se);
}
bool check(){
for (int i = 0;i < 2*n;++i){
for (int j = i+1;j < 2*n;++j){
if (!cmp(q[i].fi,q[j].fi) && !cmp(q[i].se,q[j].se)){
//cout << q[i].fi << " " << q[j].fi << " " << q[i].se << " " << q[j].se << endl;
continue;
}
bool f = 1;
for (int k = 0;k < n;++k){
//cout << i << " " << j << " " << k << endl;
//cout << sign(area(q[i],q[j],a[k])) * sign(area(q[i],q[j],b[k])) << endl;
if (sign(area(q[i],q[j],a[k])) * sign(area(q[i],q[j],b[k])) > 0){
f = 0;
break;
}
}
//cout << i << " " << j << " " << f << endl;
if (f) return true;
}
}
return false;
}
int main(){
int T;cin >> T;
while (T--){
cin >> n;
for (int i = 0,k = 0;i < n;++i){
double x1,y1,x2,y2;
cin >> x1 >> y1 >> x2 >> y2;
//cout << x1 << x2 << y1 << y2 << endl;
q[k++] = mp(x1,y1);
q[k++] = mp(x2,y2);
//if (k == 4) cout << q[2].fi << " " << q[2].se << endl;
a[i] = mp(x1,y1),b[i] = mp(x2,y2);
}
if (check()) puts("Yes!");
else puts("No!");
}
return 0;
} 
曼迪匹艾公司福利 125人发布