ZOJ 1010

这道题是考察计算几何的,主要有两个点。

一是根据有序输入的多边形的顶点求出任意多边形的面积,二是判断不相邻的边是否相交,如果相交则不构成多边形。


计算任意多边形的面积需要线性代数的知识,我也没接触过,详细的推导过程可以自行百度,介绍的很详细。

大体上就是将多边形切分成多个三角形,然后用各个三角形的矢量面积求和得出多边形面积。

最后,得出一个普适的公式,即

这里P(k)和P(k+1) 是多边形上连续的两点,将向量OP(k) 和 OP(k+1) 作叉乘,然后求和,注意最后一个点要和第一个点形成一组。


第二点,判断线段是否相交,当两个线段相交时,以其中一个线段的角度来看,另一个线段的两个端点在自身的两侧。


#include
#include
#include
typedef struct
{
    double x;
    double y;
}coor;
coor v[1000];

double cross_product(int a,int b,int c);

int main()
{
    int n,i,j,num = 0;
    while(scanf("%d",&n)!=0&&n!=0)
    {
        int flag = 1;
        double area = 0;
        num++;
        if(num>1)
        {
            printf("\n");
        }
        for(i = 0;i < n;i++)
        {
            scanf("%lf %lf",&v[i].x,&v[i].y);
        }     
        for(i = 0;i < n&&flag;i++)
        {
            int t = (i+1)%n;
            for(j = (i+1)/n;j < i-1;j++)
            {
                if(cross_product(i,j,t)*cross_product(i,j+1,t)<=0&&cross_product(j,i,j+1)*cross_product(j,t,j+1)<=0)
                {
                    flag = 0;
                    break;
                }
            }
        }
        if(flag==0||n<3)
        {
            printf("Figure %d: Impossible\n",num);
        }
        else
        {
            for(i = 0;i < n;i++)
            {
                area += v[i].x * v[(i+1)%n].y - v[(i+1)%n].x * v[i].y;
            }
            printf("Figure %d: %.2lf\n",num,fabs(area)/2);
        }
    }
    return 0;
}

double cross_product(int a,int b,int c)
{
    coor p,q;
    p.x = v[b].x - v[a].x;
    p.y = v[b].y - v[a].y;
    q.x = v[c].x - v[a].x;
    q.y = v[c].y - v[a].y;
    
    return p.x * q.y - q.x * p.y;
}

我也没有研究过计算几何,想要详细的了解本题算法的背后原理,请自行百度。

你可能感兴趣的:(编程题解)