改革春风吹满地(填补法计算多边形面积)c语言题解

Input

输入数据包含多个测试实例,每个测试实例占一行,每行的开始是一个整数n(3<=n<=100),它表示多边形的边数(当然也是顶点数),然后是按照逆时针顺序给出的n个顶点的坐标(x1, y1, x2, y2... xn, yn),为了简化问题,这里的所有坐标都用整数表示。
输入数据中所有的整数都在32位整数范围内,n=0表示数据的结束,不做处理。

Output

对于每个测试实例,请输出对应的多边形面积,结果精确到小数点后一位小数。
每个实例的输出占一行。

 思路:用一个最小的矩形框住目标多边形,矩形的长由min x和max x决定,宽由min y和min x决定.然后用矩形面积减去一个个的三角形以及余下的矩形(例如:当最左边和最下面的点之间有点,那个点会和外面的大矩形的边构造成一个矩形)

我简略画了个图:

 下面的代码中有比较详细的注释了

#include<stdio.h>
#include<string.h>
#include<math.h>
int main(){

int n;float x[105],y[105];
while(scanf("%d",&n)&&n)
{  float sum=0,s=0;
    int i=0,k=n,MINx=10000,MAXx=-10000,MINy=10000,MAXy=-10000;
    int maxx,minx,maxy,miny;
    while(n--)
    {scanf("%f%f",&x[i],&y[i]);
    if(x[i]>MAXx){maxx=i;MAXx=x[i];} //最后可知例如:最右边的坐标就是(x[maxx],y[maxx])
    if(x[i]<MINx){minx=i;MINx=x[i];}  //            最上面的坐标就是(x[maxy],y[maxy])
    if(y[i]>MAXy){maxy=i;MAXy=y[i];}  //            最左面的坐标就是(x[minx],y[minx])
    if(y[i]<MINy){miny=i;MINy=y[i];}  //            最下面的坐标就是(x[miny],y[miny])
    i++;
    }
  sum=(y[maxy]-y[miny])*(x[maxx]-x[minx]);
  for(int j=0;j<k;j++)
  {            //因为最后一个坐标和第一个坐标相连,所以要在(j+1)后面加上%k
      s+=fabs((x[j]-x[(j+1)%k])*(y[j]-y[(j+1)%k]))/2;//计算每两个坐标间的三角形面积
  //   1.左下角和右上角的计算都要拿下一个坐标即j+1去判断,
   //    如果下一个的坐标不在该开区间2和4内,则不会出现矩形
      
          //先计算左下角的矩形面积,只有当最左边的点和最下面的点中间有点才会出现矩形。
      if(y[(j+1)%k]<y[minx]&&y[(j+1)%k]>y[miny]&&x[(j+1)%k]<x[miny])
      s+=fabs((x[j]-x[(j+1)%k])*(y[(j+1)%k]-y[miny]));
              
      else if(y[(j+1)%k]>y[maxx]&&y[(j+1)%k]<y[maxy]&&x[(j+1)%k]>x[maxy]) //计算右上角
      s+=fabs((x[j]- x[(j+1)%k])*(y[(j+1)%k]-y[maxy]));
      
   //2.左上角和右下角的计算就拿当前坐标即j去判断,只要该坐标在开区间1和3内,就会出现矩形   
      
      else if(y[j]>y[minx]&&y[j]<y[maxy]&&x[j]<x[maxy])  //计算左上角
      s+=fabs((x[j]-x[(j+1)%k])*(y[j]-y[maxy]));

      else if(y[j]<y[maxx]&&y[j]>y[miny]&&x[j]>x[miny]) //计算右下角
      s+=fabs((x[j]-x[(j+1)%k])*(y[j]-y[miny]));
  }
printf("%.1f\n",sum-s);

}
return 0;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值