POJ-1127 Jack Straw(平行相交 交点坐标 计算误差)

Jack Straws

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 5349   Accepted: 2426

Description

In the game of Jack Straws, a number of plastic or wooden "straws" are dumped on the table and players try to remove them one-by-one without disturbing the other straws. Here, we are only concerned with if various pairs of straws are connected by a path of touching straws. You will be given a list of the endpoints for some straws (as if they were dumped on a large piece of graph paper) and then will be asked if various pairs of straws are connected. Note that touching is connecting, but also two straws can be connected indirectly via other connected straws.

Input

Input consist multiple case,each case consists of multiple lines. The first line will be an integer n (1 < n < 13) giving the number of straws on the table. Each of the next n lines contain 4 positive integers,x1,y1,x2 and y2, giving the coordinates, (x1,y1),(x2,y2) of the endpoints of a single straw. All coordinates will be less than 100. (Note that the straws will be of varying lengths.) The first straw entered will be known as straw #1, the second as straw #2, and so on. The remaining lines of the current case(except for the final line) will each contain two positive integers, a and b, both between 1 and n, inclusive. You are to determine if straw a can be connected to straw b. When a = 0 = b, the current case is terminated. 

When n=0,the input is terminated. 

There will be no illegal input and there are no zero-length straws. 

Output

You should generate a line of output for each line containing a pair a and b, except the final line where a = 0 = b. The line should say simply "CONNECTED", if straw a is connected to straw b, or "NOT CONNECTED", if straw a is not connected to straw b. For our purposes, a straw is considered connected to itself.

Sample Input

7
1 6 3 3 
4 6 4 9 
4 5 6 7 
1 4 3 5 
3 5 5 5 
5 2 6 3 
5 4 7 2 
1 4 
1 6 
3 3 
6 7 
2 3 
1 3 
0 0

2
0 2 0 0
0 0 0 1
1 1
2 2
1 2
0 0

0

Sample Output

CONNECTED 
NOT CONNECTED 
CONNECTED 
CONNECTED 
NOT CONNECTED 
CONNECTED
CONNECTED
CONNECTED
CONNECTED

Source

East Central North America 1994

#include <iostream>
#include <cstdio>
#include <cmath>
#define MAXN 10010
using namespace std;
double EPS=1e-8;
double add(double a,double b)
{
    if(abs(a+b)<EPS*(abs(a)+abs(b)))
    return 0;     //避免精度的误差,比如 -0.0*INF可能就是不是0了,所以将无限趋近于0的数就直接转为0,避免精度误差
    return a+b;
}
struct P
{
    double x,y;   //这里的x,y是全局变量的吧
    P()   //定义构造函数 ,构造函数必须和类同名 ,构造函数没有返回值
    {
         //可利用构造函数对类成成员赋值,也可不赋值
    };   //这个是定义无参数的函数。
    P(double x,double y):x(x),y(y){}  //定义含参的构造函数 ,用参数初始化表对对数据成员初始化。
    // 这个参数初始化表等价于
    /*
        P(int x,int y)
        {
            x=x;
            y=y;
        }
    */
    //这里的两个P是 构造函数的重载。
    P operator + (P p)
    {
        return P(add(x,p.x),add(y,p.y));
    }
    P operator - (P p)
    {
        return P(add(x,-p.x),add(y,-p.y));
    }
    P operator * (double d)
    {
        return P(x*d,y*d);
    }
    double dot(P p)   //内积
    {
        return add(x*p.x,y*p.y);
    }
    double det(P p)   //外积
    {
        return add(x*p.y,-y*p.x);
    }
};
//判断点q是否在线段p1-p2上
bool on_seg(P p1,P p2,P q) //p1-q有原来的内部x,y; 这样就等价于(p1-q) 内积 (p2-q)
{
    return (p1-q).det(p2-q)==0&&(p1-q).dot(p2-q)<=0;
}
//计算直线p1-p2与直线q1-q2的交点
P intersection(P p1,P p2,P q1,P q2)
{
    return p1+(p2-p1)*((q2-q1).det(q1-p1)/(q2-q1).det(p2-p1));
}
P    p[MAXN],q[MAXN];  //p为木棍的一端坐标,q为木棍的另一端坐标
int  a[MAXN],b[MAXN];  //a为要判断是否连接的一根稻草,b为另一根稻草。
bool g[MAXN][MAXN];    //相连关系图,表示这两根稻草是连接的
int main()
{
    int n;
    int i,j,k;
    while(scanf("%d",&n),n!=0)
    {
           for(i=0;i<n;i++)
           scanf("%lf%lf%lf%lf",&p[i].x,&p[i].y,&q[i].x,&q[i].y);
           for(i=0;i<n;i++)
          {
               g[i][i]=true;
               for(j=0;j<i;j++)
               {
                  //判断木棍i和木棍j是否有公共点,两线段是否相交
                  //外积为0则向量平行,线段一定平行
                  if((p[i]-q[i]).det(p[j]-q[j])==0)
                  {
                    //平行时
                    g[i][j]=g[j][i]=on_seg(p[i],q[i],p[j])   //这里是判断j线段的这个端点是否在线段i上。
                                   ||on_seg(p[i],q[i],q[j])  //四个一起来判断平行下是否重合的情况
                                   ||on_seg(p[j],q[j],p[i])  //毕竟是线段
                                   ||on_seg(p[j],q[j],q[i]); //这是平行情况下的相交
                  }
                  //外积不为0则向量相交,但线段不一定相交。
                  else
                  {
                    //非平行时
                    P r=intersection(p[i],q[i],p[j],q[j]);      //算出了两直线的交点坐标
                    g[i][j]=g[j][i]=on_seg(p[i],q[i],r)&&on_seg(p[j],q[j],r);  //交点必须同时在两线段上,这两根线段才重合。
                  }
               }
           }
            //通过Flory_Warshall算法判断任意两点间是否相连
           for(k=0;k<n;k++)
           for(i=0;i<n;i++)
           for(j=0;j<n;j++)
           {
               g[i][j] |= g[i][k]&&g[k][j];
           }
           int cnt=0;
           {
               while(scanf("%d%d",&a[cnt],&b[cnt]),a[cnt]&&b[cnt])
               cnt++;
           }
           for(i=0;i<cnt;i++)
           {
               puts((g[a[i]-1][b[i]-1])?"CONNECTED":"NOT CONNECTED");
           }
     }
     return 0;
}

猜你喜欢

转载自blog.csdn.net/xigongdali/article/details/81301786