Poj-3304 (叉积判断直线是否过线段)

题目

http://poj.org/problem?id=3304
题意大概就是给一些线段,问能不能找到一条直线使得这些线段在直线上的投影的交不为空。
线段数不大于100。

分析

  • 要是投影的交不为空,那么就是至少有一条垂直于那个直线的直线能经过所有线段。
  • 而且可以说明,只要有解,那么肯定可以有个解经过某两个端点。(因为直线就是被这些端点限制住的,在边界处肯定是端点)
  • 然后就枚举端点弄出一条直线,再判断一下是否经过所有选段即可。

程序

#include <cstdio>
#include <cmath>
using namespace std;
double k1,k2;
int n,T,ok;

struct node{
   
   double x,y;} U[1000],V[1000];
bool equ(node A,node B){
   
   return abs(A.x-B.x)<=0.00000001 && abs(A.y-B.y)<=0.00000001;}
bool Equ(double x,double y){
   
   return abs(x-y)<=0.00000001;}
double cheng(node v1,node v2){
   
   return v1.x*v2.y-v2.x*v1.y;}
bool check(node u,node v){
    if (equ(u,v)) return 0;
    for (int i=1; i<=n; i++){
        if (equ(u,U[i]) || equ(u,V[i]) || equ(v,U[i]) || equ(v,V[i])) continue;
        k1=cheng((node){U[i].x-u.x,U[i].y-u.y},(node){U[i].x-v.x,U[i].y-v.y});
        k2=cheng((node){V[i].x-u.x,V[i].y-u.y},(node){V[i].x-v.x,V[i].y-v.y});
        if (k1*k2>0) return 0;
    }
    return 1;
}

int main(){
    for(scanf("%d",&T); T--; ok=0){
        scanf("%d",&n);
        for (int i=1; i<=n; i++)
            scanf("%lf%lf%lf%lf",&U[i].x,&U[i].y,&V[i].x,&V[i].y);
        for (int i=1; i<=n && !ok; i++)
            for (int j=i; j<=n && !ok; j++){
                ok=check(U[i],U[j])||check(U[i],V[j])||check(V[i],U[j])||check(V[i],V[j]);
            }
        puts(ok?"Yes!":"No!");
    }
}

提示

  • 我觉得也可以枚举一个端点,假设直线过这个端点,然后利用其它线段来限制住这条直线的斜率,看看最后斜率的可取区间是否为空,可是不知道为什么过不了,代码放下面,也请帮忙看看吧。
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
struct node{
   
   double x,y;} U[20000],V[20000];
double Max,Min,mn,mx,k1,k2,k3,k4;
int n,ok,T;
double K(node A,node B){
    if (A.x==B.x) return 99999999999999999999999999999.0;
    return (A.y-B.y)/(A.x-B.x);
}
bool equ(node A,node B){
   
   return abs(A.x-B.x)<=0.00000001 && abs(A.y-B.y)<=0.00000001;}
bool dy(double x,double y){
   
   return x-y>0.0001;}
bool xy(double x,double y){
   
   return y-x>0.0001;}
bool check(node O){
    Min=-99999999999999999999999999999.0;
    Max=99999999999999999999999999999.0;
    for (int i=1; i<=n; i++) if(!equ(O,U[i]) && !equ(O,V[i])){
        k1=K(O,U[i]);
        k2=K(O,V[i]);
        mn=min(k1,k2),mx=max(k1,k2);
        if (dy(mn,Max) || xy(mx,Min)) return 0;
        if (xy(mx,Max)) Max=mx;
        if (dy(mn,Min)) Min=mn;
        if (dy(Min,Max)) return 0;
    }
    return 1;
}

int main(){

    for (scanf("%d",&T); T--;){
        ok=0;
        scanf("%d",&n);
        for (int i=1; i<=n; i++) scanf("%lf%lf%lf%lf",&U[i].x,&U[i].y,&V[i].x,&V[i].y);
        for (int i=1; i<=n && !ok; i++)
            if (check(U[i]) || check(V[i])) ok=1;
        puts(ok?"Yes!":"No!");
    }
}

猜你喜欢

转载自blog.csdn.net/jackypigpig/article/details/78629588