1. 程式人生 > >POJ 3304 Segments [列舉+叉乘判斷線段相交]【計算幾何】

POJ 3304 Segments [列舉+叉乘判斷線段相交]【計算幾何】

Segments
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 11920 Accepted: 3757

Description

Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments on it, all projected segments have at least one point in common.

Input

Input begins with a number T showing the number of test cases and then, T test cases follow. Each test case begins with a line containing a positive integer n ≤ 100 showing the number of segments. After that, n lines containing four real numbers x1 y1 x2 y2 follow, in which (x1, y1) and (x2, y2) are the coordinates of the two endpoints for one of the segments.

Output

For each test case, your program must output “Yes!”, if a line with desired property exists and must output “No!” otherwise. You must assume that two floating point numbers a and b are equal if |a - b| < 10-8.

Sample Input

3
2
1.0 2.0 3.0 4.0
4.0 5.0 6.0 7.0
3
0.0 0.0 0.0 1.0
0.0 1.0 0.0 2.0
1.0 1.0 2.0 1.0
3
0.0 0.0 0.0 1.0
0.0 2.0 0.0 3.0
1.0 1.0 2.0 1.0
Sample Output

Yes!
Yes!
No!
Source

Amirkabir University of Technology Local Contest 2006

題目大意 :
就是給你一堆線段 問你是否存在這樣一條直線 使得所有線段在直線上的投影均有公共部分 有輸出Yes 沒有輸出No

解題方法 :
投影直線上有公共點的話就是說這條直線存在一個垂線經過所有線段 就是與所有線段均相交

只要列舉這些線段端點所確定的直線 是否存在一條與所有線段均相交即可

判斷線段相交用的是叉乘 首先用兩點p1,p2確定了一條直線 在用p1,p2分別與計算線段兩個端點計算叉乘即可
叉乘之積>0就說明線段兩端點在直線的同側 也就是直線不經過此線段

注意 :
本題是double型別
判斷是否有重點 重點定義為座標非常接近的兩點 <1e-8即可
判斷叉乘之積時 只要<1e-8 即可

附本題程式碼

這是引用網上與我程式碼非常接近的大神的程式碼 能Ac 但我的不知為什麼就是不行 ~>_<~ 但也在下面貼出來了 如果有人找到BUG 了 一定要回復我 不勝感激

#include <iostream>
#include <math.h>
#include <cstdio>
using namespace std;
#define MAXM 110
#define EPS 1e-8

typedef struct{
    double x1,y1,x2,y2;
}Segment;

Segment segment[MAXM];
int n;

double distance(double x1,double y1,double x2,double y2){
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

double corss(double x1,double y1,double x2,double y2,double x,double y){
    return (x2-x1)*(y-y1)-(x-x1)*(y2-y1);
}

bool judge(double x1,double y1,double x2,double y2){
    int i;
    if(distance(x1,y1,x2,y2)<EPS) return 0;
    for(i=0;i<n;i++){
        if(corss(x1,y1,x2,y2,segment[i].x1,segment[i].y1)*
            corss(x1,y1,x2,y2,segment[i].x2,segment[i].y2)>EPS) return 0;
    }
    return 1;
}

int main(){
    int t,i,j,ans;
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(i=0;i<n;i++)
            scanf("%lf%lf%lf%lf",&segment[i].x1,&segment[i].y1,&segment[i].x2,&segment[i].y2);
        if(n==1) {printf("Yes!\n");continue;}

        ans=0;
        for(i=0;i<n && !ans;i++)
            for(j=i+1;j<n && !ans;j++){
                if(judge(segment[i].x1,segment[i].y1,segment[j].x1,segment[j].y1) ||
                    judge(segment[i].x1,segment[i].y1,segment[j].x2,segment[j].y2) ||
                    judge(segment[i].x2,segment[i].y2,segment[j].x1,segment[j].y1) ||
                    judge(segment[i].x2,segment[i].y2,segment[j].x2,segment[j].y2))
                    ans=1;
            }
        if(ans) printf("Yes!\n");
        else printf("No!\n");
    }
    return 0;
}


我那錯誤的程式碼>_<


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int n,m;

//精度是個大問題啊  很重要  判斷重點
const double eps = 1E-8;

struct point
{
    double  x,y;
} pzuo[1005],pyou[1005];

int dis (const point &p1,const point &p2)
{
    return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}

int mul(const point &p1,const point &p2,const point &p3)
{
    return (p2.x-p1.x)*(p3.y-p1.y)-(p3.x-p1.x)*(p2.y-p1.y);
}

int judge(const point &p1,const point &p2)
{
    if(dis(p1,p2)<eps)  return 0;
    for(int i=0; i<n; i++)
        if(mul(p1,p2,pzuo[i])*mul(p1,p2,pyou[i])>eps)
            return 0;

    return 1;
}

int solve()
{
    for(int i=0; i<n; i++)
        for(int j=i+1; j<n; j++)
            if(judge(pzuo[i],pzuo[j])||
                    judge(pzuo[i],pyou[j])||
                    judge(pyou[i],pzuo[j])||
                    judge(pyou[i],pyou[j]))
                return 1;

    return 0;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0; i<n; i++)
            scanf("%lf%lf%lf%lf",&pzuo[i].x,&pzuo[i].y,&pyou[i].x,&pyou[i].y);
        if(n==1)
        {
            printf("Yes!\n");
            continue;
        }
        if(solve())     printf("Yes!\n");
        else            printf("No!\n");
    }
    return 0;
}