线段交点

线段交点

题目描述:
给定N个线段。求线段交点数。
保证没有两条线段共线
输入:
一行一个整数N,表示线段的个数
第2~N+1行,每行四个实数,x1,y1,x2,y2,表示线段的两个端点(x1,y1)和(x2,y2)
输出:
一行一个整数,表示线段交点数。
样例输入1:
3
0.00 0.00 1.00 1.00
0.00 1.00 1.00 0.00
0.00 0.00 1.00 0.00
样例输出1:
3
样例输入2:
3
0.00 0.00 1.00 1.00
0.00 0.00 1.00 0.00
0.00 0.00 0.00 1.00
样例输出2:
1
(没错这就是上一个题改了一下,其实是我把之前题看错了做的解法,然后,emmm,改成这个题意,就OK了)
先把坐标都换成向量,然后计算交点。

double getCrossPointx(STU s1, STU s2)
{
    Point a;
    a.y=s2.y2-s2.y1;
    a.x=s2.x2-s2.x1;
    Point b;
    b.y=s1.y1-s2.y1;
    b.x=s1.x1-s2.x1;
    Point c;
    c.y=s1.y2-s2.y1;
    c.x=s1.x2-s2.x1;
    double d1 = fabs(waiji(a, b));
    double d2 = fabs(waiji(a, c));
    double t = d1 / (d1 + d2);
    return 1.0*s1.x1 + (s1.x2 - s1.x1) * t;
}
double getCrossPointy(STU s1, STU s2)
{
    Point a;
    a.y=s2.y2-s2.y1;
    a.x=s2.x2-s2.x1;
    Point b;
    b.y=s1.y1-s2.y1;
    b.x=s1.x1-s2.x1;
    Point c;
    c.y=s1.y2-s2.y1;
    c.x=s1.x2-s2.x1;
    double d1 = fabs(waiji(a, b));
    double d2 = fabs(waiji(a, c));
    double t = d1 / (d1 + d2);
    return 1.0*s1.y1 + (s1.y2 - s1.y1) * t;
}

跟前面那个结合一下,就变成了这样:

#include<bits/stdc++.h>
using namespace std;
struct Point//向量
{
    double x;
    double y;
};
typedef struct
{
    double x1;
    double y1;
    double x2;
    double y2;
    Point p1;
    Point p2;
}STU;
double maxx(double a,double b)
{
    if(a>b) return a;
    else return b;
}
double minn(double a,double b)
{
    if(a>b) return b;
    else return a;
}
bool judge1(STU a,STU b)
{
    if(maxx(a.x1,a.x2)<minn(b.x1,b.x2)||maxx(a.y1,a.y2)<minn(b.y1,b.y2)||minn(a.x1,a.x2)>maxx(b.x1,b.x2)||minn(a.y1,a.y2)>maxx(b.y1,b.y2))
    {
        return false;
    }
    else return true;
}
bool judge2(STU a,STU b)
{
    if((1.0*(a.x1-b.x1)*(b.y2-b.y1)-1.0*(a.y1-b.y1)*(b.x2-b.x1))*(1.0*(a.x2-b.x1)*(b.y2-b.y1)-1.0*(a.y2-b.y1)*(b.x2-b.x1))>0.000001)
    {
        return false;
    }
    else if((1.0*(b.x1-a.x1)*(a.y2-a.y1)-1.0*(b.y1-a.y1)*(a.x2-a.x1))*(1.0*(b.x2-a.x1)*(a.y2-a.y1)-1.0*(b.y2-a.y1)*(a.x2-a.x1))>0.000001)
    {
        return false;
    }
    else return true;
}
bool xiangjiao(STU a,STU b)
{
    if(!judge1(a,b)) return false;
    else if(!judge2(a,b)) return false;
    else return true;
}
double waiji(Point a, Point b)
{
    return 1.0*a.x*b.y - a.y*b.x;
}
double getCrossPointx(STU s1, STU s2)//求交点横坐标
{
    Point a;
    a.y=s2.y2-s2.y1;
    a.x=s2.x2-s2.x1;
    Point b;
    b.y=s1.y1-s2.y1;
    b.x=s1.x1-s2.x1;
    Point c;
    c.y=s1.y2-s2.y1;
    c.x=s1.x2-s2.x1;
    double d1 = fabs(waiji(a, b));
    double d2 = fabs(waiji(a, c));
    double t = d1 / (d1 + d2);
    return 1.0*s1.x1 + (s1.x2 - s1.x1) * t;
}
double getCrossPointy(STU s1, STU s2)//求交点纵坐标
{
    Point a;
    a.y=s2.y2-s2.y1;
    a.x=s2.x2-s2.x1;
    Point b;
    b.y=s1.y1-s2.y1;
    b.x=s1.x1-s2.x1;
    Point c;
    c.y=s1.y2-s2.y1;
    c.x=s1.x2-s2.x1;
    double d1 = fabs(waiji(a, b));
    double d2 = fabs(waiji(a, c));
    double t = d1 / (d1 + d2);
    return 1.0*s1.y1 + (s1.y2 - s1.y1) * t;
}
int main()
{
    int n,sum=0;
    cin>>n;
    STU stu[n+1];
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf%lf%lf",&stu[i].x1,&stu[i].y1,&stu[i].x2,&stu[i].y2);
        stu[i].p1.x=stu[i].x1;
        stu[i].p1.y=stu[i].y1;
        stu[i].p2.x=stu[i].x2;
        stu[i].p2.y=stu[i].y2;
    }
    int u=0,v=0;
    Point po[100000];
    for(int i=1;i<n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if(xiangjiao(stu[i],stu[j])) sum++;
            Point p;
            p.x=getCrossPointx(stu[i],stu[j]);
            p.y=getCrossPointy(stu[i],stu[j]);
            for(int k=0;k<u;k++)//判断是否重复
            {
                if(p.x==po[k].x&&p.y==po[k].y)
                {
                    v=1;
                    break;
                }
            }
            if(v==0)
            {
                po[u].x=p.x;
                po[u].y=p.y;
                u++;
            }
            else sum--;//重复,则不应该+1,但前面已经加了,故在此处减去
        }
    }
    printf("%d\n",sum);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值