hdu 1086 You can Solve a Geometry Problem too

来源:互联网 发布:淘宝是谁的创始人 编辑:程序博客网 时间:2024/06/04 23:27

You can Solve a Geometry Problem too


Description

Many geometry(几何)problems were designed in the ACM/ICPC. And now, I also prepare a geometry problem for this final exam. According to the experience of many ACMers, geometry problems are always much trouble, but this problem is very easy, after all we are now attending an exam, not a contest :)
Give you N (1<=N<=100) segments(线段), please output the number of all intersections(交点). You should count repeatedly if M (M>2) segments intersect at the same point.

Note:
You can assume that two segments would not intersect at more than one point. 
 

Input

Input contains multiple test cases. Each test case contains a integer N (1=N<=100) in a line first, and then N lines follow. Each line describes one segment with four float values x1, y1, x2, y2 which are coordinates of the segment’s ending. 
A test case starting with 0 terminates the input and this test case is not to be processed.
 

Output

For each case, print the number of intersections, and one line one case.
 

Sample Input

20.00 0.00 1.00 1.000.00 1.00 1.00 0.0030.00 0.00 1.00 1.000.00 1.00 1.00 0.0000.00 0.00 1.00 0.000
 

Sample Output

13
#include <stdio.h>#include <string.h>#include <math.h>#include <iostream>#include <algorithm>#define maxin 14997#define sign(a) ((a)>0?1:(((a)<0?-1:0)))const double INF = 1E200;const double EP = 1E-10;using namespace std;struct point{    double x;    double y;};struct line{    point s;    point e;};struct line lin[110];int xmult(point p1,point p2,point p0){    //证明p1,p0所在的直线l1和p2,p0所在的直线l2斜率相等,也就是说三点共线    return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);}//判三点共线int dots_inline(point p1,point p2,point p3)//传入一条直线两个端点和另一条直线的其中一个端点{    return !xmult(p1,p2,p3);//如果xmult的返回值为0,代表三点共线,则说明p1,p2所组成的线段与p3所在的线段相交于端点相交}//判两点在直线同侧,点在直线上返回0int same_side(point p1,point p2,line l)//传入一条直线的端点和另一条直线,通过判断两个点是否在这条直线的同一边,判断是否相交{    return sign(xmult(l.s,p1,l.e))*xmult(l.s,p2,l.e)>0;    //判断三点是否共线,如果返回值为0,也就是共线,乘号前边值就为0,如果返回值大于零,乘号前边值为1,如果返回值小于0,    //乘号前边值为-1,接着再判断另一个点是否和那条直线的两端点共线,返回两种情况下的乘绩    //调用xmult函数是为了判断一条直线的端点是否在另一条直线的两边,只要不共线,返回非零值。所以,只要    //乘绩为负值,就说明在两边,返回0;}//判点是否在线段上,包括端点和部分重合//给出一条边的一个点和另一条边int dot_online_in(point p,line l){    //该点和另一条边重合并且该交点在线段内    return !xmult(p,l.s,l.e)&&(l.s.x-p.x)*(l.e.x-p.x)<=0&&(l.s.y-p.y)*(l.e.y-p.y)<=0;}//该函数的返回值为1,代表有交点int intersect_in(line u,line v){        if (!dots_inline(u.s,u.e,v.s)||!dots_inline(u.s,u.e,v.e))//判断线段u和线段v是否相交于端点,如果返回的是1,即有交点,在该判断中用的是!(),即返回为0(没有和端点相交)的时候才会进入if语句        return !same_side(u.s,u.e,v)&&!same_side(v.s,v.e,u);//判断两条直线相交,即判断任意一条直线的两端点在另一条直线的两边    //下面的调用实际上是证明了有一条直线的端点和另一条直线相交    return dot_online_in(u.s,v)||dot_online_in(u.e,v)||dot_online_in(v.s,u)||dot_online_in(v.e,u);}int main(){    int n,i,j,k;    point a,b;    while(scanf("%d",&n),n)    {        for(i = 0; i < n; i++)        {            scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);            lin[i].s = a;            lin[i].e = b;        }        int num = 0;        for(j = 0; j < n; j++)        {            for(k = 0; k < n; k++)            {                if(j == k)                    continue;                int bo = intersect_in(lin[j],lin[k]);                if(bo == 1)                    num++;            }        }        printf("%d\n",num/2);    }    return 0;}


0 0