周末小测——A(POJ 1410 Intersection(计算几何))

来源:互联网 发布:三生网络直销 编辑:程序博客网 时间:2024/05/16 17:20

我只想吐槽下,找来这道题的同学,本来抱着有第一题在,绝对不会挂0的想法。

眼睁睁的看着时间刷的流走——在我在图纸上演算的时候,时间已经过去半个多小时。

明明是数据结构的小测,竟出现了计算几何来打酱油。

一直对这题没有任何想法,我更想吐槽我自己,我一直觉得自己虽然不是拔尖的数学人才,但也不算弱吧。

哎呀妈,这道让我深刻认识到,学如逆水行舟,不进则退。我连斜率竟然都迷茫了。大哭

Description

You are to write a program that has to decide whether a given line segment intersects a given rectangle.

An example:
line: start point: (4,9)
end point: (11,2)
rectangle: left-top: (1,5)
right-bottom: (7,1)


Figure 1: Line segment does not intersect rectangle

The line is said to intersect the rectangle if the line and the rectangle have at least one point in common. The rectangle consists of four straight lines and the area in between. Although all input values are integer numbers, valid intersection points do not have to lay on the integer grid.

Input

The input consists of n test cases. The first line of the input file contains the number n. Each following line contains one test case of the format:
xstart ystart xend yend xleft ytop xright ybottom

where (xstart, ystart) is the start and (xend, yend) the end point of the line and (xleft, ytop) the top left and (xright, ybottom) the bottom right corner of the rectangle. The eight numbers are separated by a blank. The terms top left and bottom right do not imply any ordering of coordinates.

Output

For each test case in the input file, the output file should contain a line consisting either of the letter "T" if the line segment intersects the rectangle or the letter "F" if the line segment does not intersect the rectangle.

Sample Input

14 9 11 2 1 5 7 1

Sample Output

F

问题:

1.题目中没有说清楚,线段在矩形内部,算不算是相交( 根据题意跟AC代码看,这里应该算是相交的)。

2.判断两个线段相交时,注意它们在一条直线上的情况。

3.输入的左上(x1,y2)与右下(x2,y1),未必有x1<x2和y1<y2。

题意:

就是给出一个矩形的左上和右下的点,以及一条线段。判断线段和矩形的四条边是否有相交。

考点:计算几何(判断线段是否相交)(包含端点)

方法:

方法一、计算几何中的判断两条线段是否相交,快速排斥实验,跨立实验。

转的代码:

#include <iostream>#include <cstdio>#include <cmath>using namespace std;const double eps = 1e-8;struct Point {    double x, y;};double Max(double a, double b) {    return a > b ? a : b;}double Min(double a, double b) {    return a > b ? b : a;}double Multi(Point p1, Point p2, Point p0) {    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);}int dblcmp(double m) {    if (fabs(m) < eps) return 0;    return m > 0 ? 1 : -1;}//注意处理非规范相交,例如与边的端点相交,或与边共线相交的情况bool Cross(Point a, Point b, Point c, Point d) {    if (dblcmp(Max(a.x, b.x)-Min(c.x, d.x)) >= 0 && dblcmp(Max(c.x, d.x)-Min(a.x, b.x)) >= 0        && dblcmp(Max(a.y, b.y)-Min(c.y, d.y)) >= 0 && dblcmp(Max(c.y, d.y)-Min(a.y, b.y)) >= 0        && dblcmp(Multi(a, d, c)*Multi(b, d, c)) <= 0 && dblcmp(Multi(c, b, a)*Multi(d, b, a)) <= 0)                return true;    return false;}int main(){    int n;    double x1, x2, y1, y2, xl, xr, yup, ydown;    Point a, b, p1, p2, p3, p4;    bool flag;    scanf ("%d", &n);    while (n--) {         scanf ("%lf%lf%lf%lf%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y, &x1, &y1, &x2, &y2);         xl = Min(x1, x2);         xr = Max(x1, x2);         yup = Max(y1, y2);         ydown = Min(y1, y2);         flag = false;         if (Max(a.x, b.x) < xr && Max(a.y, b.y) < yup && Min(a.x, b.x) > xl && Min(a.y, b.y) > ydown)            flag = true;         else {            p1.x = p2.x = xl;            p1.y = p4.y = ydown;            p2.y = p3.y = yup;            p3.x = p4.x = xr;            if (Cross(a, b, p1, p2) || Cross(a, b, p2, p3) || Cross(a, b, p3, p4) || Cross(a, b, p4, p1))                flag = true;         }         if (flag) printf ("T\n");         else printf ("F\n");    }    return 0;}

方法二、

单从这道题上看,我们可以从他的反面来解决这个问题,即找出不想交的情况。

//我从反面考虑,将不相交的情况列举出来#include <stdio.h>int main(){int x1,y1,x2,y2,xl,yt,xr,yb,i,n,a,b,c,f1,f2,f3,f4,temp;scanf("%d",&n);for(i=0;i<n;i++){scanf("%d%d%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&xl,&yt,&xr,&yb);if(xl>xr){temp=xl;xl=xr;xr=temp;}if(yt<yb){temp=yt;yt=yb;yb=temp;}a=y1-y2;b=x2-x1;c=x1*y2-y1*x2;f1=a*xl+b*yb+c;f2=a*xl+b*yt+c;f3=a*xr+b*yb+c;f4=a*xr+b*yt+c;if(f1>0&&f2>0&&f3>0&&f4>0||f1<0&&f2<0&&f3<0&&f4<0) //判断线段所在直线是否与矩形相交printf("F\n");else if((x1>xr&&x2>xr)||(x1<xl&&x2<xl))//若线段所在直线与矩形相交,则满足一下两种情况的时候线段不与矩形相交printf("F\n");else if((y1>yt&&y2>yt)||(y1<yb&&y2<yb))printf("F\n");elseprintf("T\n");}return 0;}

方法三、

Cohen-Sutherland线段裁剪算法


加油,↖(^ω^)↗争取下次再碰到一次A过。


0 0
原创粉丝点击