Segments

题目链接:https://vjudge.net/problem/POJ-3304

题意:给你n个线段,问是否可以找到一条直线,使得所有线段在这条直线上的投影有公共部分。

思路:题目说要找到一条直线使得所有线段在直线上的投影至少有一个公共点,这样感觉有点难,可以变一下形。如果说线段们的投影有公共点的话,那么可以说是过线段的两个端点做垂线以后得到的新线段有公共点,这些线段如果有公共点,那么可以过这个公共点做条垂线,那么这条直线必然穿过所有线段。所以说我们就可以去找这样一条直线,如果说这条直线穿过了所有的线段的中间,那么我们可以把它往下移一点点,使得直线经过一个端点,然而只过一个端点还是不行,那可以旋转一下,让这条线过两个端点,那就只要判断这条直线是否穿过所有线段即可。

//#include <bits/stdc++.h>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const double eps=1e-10;
struct node
{
    double x,y;
} b[505];
double chaj(double x1,double y1,double x2,double y2)
{
    return x1*y2-y1*x2;
}
bool fun(double x1,double y1,double x2,double y2,int m)
{
    bool v=true;
    for(int i=1; i<=m; i+=2)
    {
        if( chaj(x2-x1,y2-y1,b[i].x-x1,b[i].y-y1)*chaj(x2-x1,y2-y1,b[i+1].x-x1,b[i+1].y-y1) >0 )
            v=false;
    }
    return v;
}
int dcmp(double x)
{
    if(fabs(x)<eps)
        return 0;
    else
        return x<0?-1:1;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        int m=0;
        for(int i=1; i<=n; i++)
        {
            double x,y,z,w;
            cin>>x>>y>>z>>w;
            b[++m].x=x;
            b[m].y=y;
            b[++m].x=z;
            b[m].y=w;
        }
        bool v=false;
        for(int i=1; i<m; i++)
        {
            for(int j=i+1; j<=m; j++)
            {
                if(dcmp(b[i].x-b[j].x)==0&&dcmp(b[i].y-b[j].y)==0)//double有点误差,这里必须判断下,不然会wa
                    continue;
                if(fun(b[i].x,b[i].y,b[j].x,b[j].y,m))
                    v=true;
            }
        }
        if(v)
            cout<<"Yes!"<<endl;
        else
            cout<<"No!"<<endl;
    }
}
原文地址:https://www.cnblogs.com/zcb123456789/p/13662688.html