zoj 1010 Area (叉积求面积 与 跨立相交实验判断相交)

版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/83302445

题目链接:zoj 1010

题意:给你 N  个点的坐标,点是按照顺序输入的。每一个点都与它后面的那个点连成一条线段,最后一个点与起点相连。

求组成的多边形的面积。

参考博客:https://blog.csdn.net/freezhanacmore/article/details/10181361

解题思路:根据叉积的标量意义两向量叉积得到新向量长度为这两个所构成的平行四边形的面积,利用这个性质我们可以求三角形的面积(除以2就好了)。

这题关键不在求多边形的面积,而在于判断这个多边形是否合法,

这里的不合法指的是只要存在一条线段不和它直接首尾相连任意一条线段相交,  就表示面积不可求,输出 impossible

然后就是线段的比较判断问题:


注意: 是要与不和当前线段直接相连的每一条线段都比较。
          那么我们每次加入一个点,直接判断新形成的线段与前面所有出现过的不直接相连的比较就可以了

所以应该从第三条线段开始枚举。
因为第一条线段没有线段可以和它比较;
第二条线段前面只有一条线段,而这条线段又是和他直接相连的,所以不用比较。
这样一直到了第 N-1 条线段都可以这么判断下去。

然后注意到最后一条线段是终点和起点相连形成的,所以它不能和第一条线段比较,也不可以和第 n-1 条线段比较。

还有注意一点的是:相交于端点也要算进去

最后就是叉积求面积了。





#include<bits/stdc++.h>
using namespace std;

const int maxn=1010;
int n;

struct point
{
    double x,y;
    point() {}

    point(double _x,double _y)
    {
        x=_x;
        y=_y;
    }

    point operator -(const point &b) const {
        return point(x-b.x,y-b.y);
    }
}p[maxn];


double Cross(point a,point b) ///叉积
{
    return a.x*b.y-a.y*b.x;
}

double esp=1e-8;
int dcmp(double x)
{
    if(fabs(x)<esp) return 0;
    else return x>0?1:-1;
}
bool isCross(point s1,point e1,point s2,point e2)///判断两次跨立相交
{
    ///第一步,快速排斥实验
    if(!(min(s1.x,e1.x)<=max(s2.x,e2.x)&&min(s2.x,e2.x)<=max(s1.x,e1.x)&&
       min(s1.y,e1.y)<=max(s2.y,e2.y)&&min(s2.y,e2.y)<=max(s1.y,e1.y))) return false;

    ///首先判断向量s2e2 跨立 向量s1e1
    double c1=Cross(s2-s1,e1-s1),c2=Cross(e1-s1,e2-s1);
    ///再次判断向量s1e1 跨立 向量 s2e2
    double c3=Cross(s1-s2,e2-s2),c4=Cross(e2-s2,e1-s2);

    ///==0表示,相交于端点也认定为相交
    if(dcmp(c1*c2)>=0&&dcmp(c3*c4)>=0) return true;

    return false;
}

bool haveCross()
{

    ///从第三条线段开始,一直到第N-1条线段
    for(int i=2;i<n-1;i++)
    {
        for(int j=1;j<i;j++)///与前面每一条不直接相连的线段
        {
            if(isCross(p[i],p[i+1],p[j-1],p[j])){
                return true;
            }
        }
    }

    ///判断最后一条线段 p[n-1]_p[0]
    ///从第二条线段一直比较到n-2条线段
    for(int i=1;i<n-2;i++){
        if(isCross(p[n-1],p[0],p[i],p[i+1])){
            return true;
        }
    }

    return false;
}
double Area()
{
    double area=0;

    for(int i=1;i<n-1;i++)
        area+=Cross(p[i]-p[0],p[i+1]-p[0]);

    return fabs(area)/2.0;
}
int main()
{
    int ncase=0;

    while(scanf("%d",&n)&&(n!=0))
    {
        double a,b;

        for(int i=0;i<n;i++){

            scanf("%lf%lf",&a,&b);
            p[i]=point(a,b);
        }

        if(n<3) {
            printf("Figure %d: Impossible\n\n",++ncase);
            continue;
        }

        if(haveCross()){
            printf("Figure %d: Impossible\n\n",++ncase);
            continue;
        }
        else {
            printf("Figure %d: %.2f\n\n",++ncase,Area());
        }
    }

    return 0;
}















 

猜你喜欢

转载自blog.csdn.net/LJD201724114126/article/details/83302445