• HDOJ(2056)&HDOJ(1086)


    Rectangles    HDOJ(2056)

    http://acm.hdu.edu.cn/showproblem.php?pid=2056

    题目描述:给2条线段,分别构成2个矩形,求2个矩形相交面积。

    算法:先用快速排斥判断2个矩形是否相交。若不相交,面积为0。若相交,将x坐标排序去中间2个值之差,y坐标也一样。最后将2个差相乘得到最后结果。

    这题是我大一的时候做过的,当时一看觉得很水,写起来发现其实没我想的那么水。分了好几类情况没做出来。今天看了点关于判断线段相交的知识,想起了这题便拿来练手。快速排斥之后又准备分类讨论,越想分类情况越多。后来意外想到了取各自坐标方向的2个中值之差(如x1,x2,x3,x4,是按从小到大排列的,取x3-x2,同理y3-y2)。最后2个差相乘就是相交面积。泪牛满面!

    #include <iostream>
    #include <iomanip>
    #include <cstdlib>
    using namespace std;
    int cmp(const void *a,const void *b)
    {
        return *(double*)a-*(double*)b;
    }
    double min(double a,double b)
    {
        return a<b?a:b;
    }
    double max(double a,double b)
    {
        return a>b?a:b;
    }
    bool intersected(double x1,double y1,double x2,double y2,double x3,double y3,double x4,double y4)
    {
        if(min(x1,x2)<max(x3,x4)&&
           min(x3,x4)<max(x1,x2)&&
           min(y1,y2)<max(y3,y4)&&
           min(y3,y4)<max(y1,y2))   //快速排斥判断2矩形是否相交
            return true;
        else
            return false;
    }
    double getmiddiff(double a[4])  //取次小和次大的2个数之差,没想到好的办法,于是用了快排
    {
        qsort(a,4,sizeof(double),cmp);  
        return a[2]-a[1];
    }
    int main()
    {
        double x1,y1,x2,y2,x3,y3,x4,y4;
        double temp[4];
        while(cin>>x1>>y1>>x2>>y2>>x3>>y3>>x4>>y4)
        {
            if(intersected(x1,y1,x2,y2,x3,y3,x4,y4))
            {
                temp[0]=x1;
                temp[1]=x2;
                temp[2]=x3;
                temp[3]=x4;
                double xdiff=getmiddiff(temp);
                temp[0]=y1;
                temp[1]=y2;
                temp[2]=y3;
                temp[3]=y4;
                double ydiff=getmiddiff(temp);
                cout<<fixed<<setprecision(2)<<xdiff*ydiff<<endl;    //需要<iomanip>
            }
            else
                cout<<"0.00"<<endl;   //一开始是cout<<"0"<<endl;WA了一次,SB
        }
        return 0;
    }
    View Code

    You can Solve a Geometry Problem too     HDOJ(1086)

    http://acm.hdu.edu.cn/showproblem.php?pid=1086

    题目描述:给n条线段,求相交点的个数。

    算法:老套路,遍历任意两条线段,用快速排斥判断2个矩形是否相交。这题用跨立实验,即以其中一条线段为直线,判断另一线段的两端点是否在它两边。使用2次跨立实验。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    struct line
    {
        double x1,y1;
        double x2,y2;
    };
    bool Exclude(line l1,line l2) //快速排斥
    {
        if(min(l1.x1,l1.x2)<=max(l2.x1,l2.x2)
            &&min(l2.x1,l2.x2)<=max(l1.x1,l1.x2)
            &&min(l1.y1,l1.y2)<=max(l2.y1,l2.y2)
            &&min(l2.y1,l2.y2)<=max(l1.y1,l1.y2)) //相等的时候说明2个矩形有公共点
            return true;
        else
            return false;
    }
    bool Straddle(line l1,line l2)  //跨立实验
    {
        //3个向量
        double t1=l1.x1-l1.x2;
        double w1=l1.y1-l1.y2;
    
        double t2=l1.x1-l2.x1;
        double w2=l1.y1-l2.y1;
    
        double t3=l1.x1-l2.x2;
        double w3=l1.y1-l2.y2;
        //求叉积
        double cross1_2=(t1*w2-t2*w1);
        double cross1_3=(t1*w3-t3*w1);
        if(cross1_2*cross1_3<=0)
            return true;
        else
            return false;
    }
    bool isIntersect(line l1,line l2)
    {
        if(Exclude(l1,l2)&&Straddle(l1,l2)&&Straddle(l2,l1))
            return true;
        else
            return false;
    }
    int main()
    {
        int n,res;
        vector<line> v;
        while(cin>>n&&n)
        {
            v.clear();
            line temp;
            res=0;
            for(int i=0;i<n;i++)
            {
                cin>>temp.x1>>temp.y1>>temp.x2>>temp.y2;
                v.push_back(temp);
            }
            int len=v.size();
            for(int i=0;i<len-1;i++)
            {
                for(int j=i+1;j<len;j++)
                {
                    if(isIntersect(v[i],v[j]))
                        res++;
                }
            }
            cout<<res<<endl;
        }
        return 0;
    }
    View Code

    跨立实验可用叉积来解决:设这四个点为x1,y1,x2,y2,x3,y3,x4,y4L1的坐标为t1=x1-x2,w1=y1-y2,1端点到3,4的线段向量分别为t2=x1-x3,w2=y1-y3,t3=x1-x4,w3=y1-y4;则3,4在L1两端即为(t1*w2-t2*w1)*(t1*w3-t3*w1)<=0 ,如果等于0则有一点在直线L1上,属于非规范相交判断L1的两点在L2两侧同理。

  • 相关阅读:
    设置win 10 软件开机启动
    win10 无法使用内置管理员账户打开应用
    设置 npm 源为淘宝镜像
    git sh.exe 乱码
    mybatis 获取新增数据的主键
    框架 get 请求乱码
    js在浏览器下的区别小结(部分)
    js调试的一点小知识
    git常用命令
    css水平居中(一)
  • 原文地址:https://www.cnblogs.com/chiry/p/3505097.html
Copyright © 2020-2023  润新知