hdu 1086 You can Solve a Geometry Problem too

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

    
    
2 0.00 0.00 1.00 1.00 0.00 1.00 1.00 0.00 3 0.00 0.00 1.00 1.00 0.00 1.00 1.00 0.000 0.00 0.00 1.00 0.00 0
 

Sample Output

    
    
1 3
#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所在的线段相交于端点相交
}

//判两点在直线同侧,点在直线上返回0
int 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器学习模型机器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值