这次是一道计算几何的题 思路想到的话代码不难写 比较坑的是 当时怕超时 没有用c++写 因为好久没用c语言 结果忘加!=EOF了 一直超时 最后发现了 被队友笑了好久
首先说一下题意
题意说的是按顺序给出一个多边形的所有点 然后有Q次询问 每次给两个点 问这两个点把多边形分成的两个部分中面积较小的那个
接下来说一下思路吧 首先询问次数有点大 每次算面积的时候还要跑一边循环 暴力是绝对会超时的 所以只能优化 询问次数是不能减少的 所以只能从求多变形面积上面下手优化时间 首先多边形的面积公式是 S =0.5* (x1*y2 -y1*x2+x2*y3 - y2*x3.....xn*y1-yn*x1) 最开始的时候想到的是预处理 纯暴力的预处理 结果发现还是超时 因为每次都会重复计算很多已经算过的值 观察多边形 其实可以发现 多边形其实可以看成许多个三角形组成的 又因为输入的时候的点是按顺序给出的 所以可以先预处理从第一个点开始到任意一点之间的多边形的面积 只要在输入的时候 每次算一个三角形的面积 再加上上一步已经算出的多边形面积就可以 这时候得到一个以第一个点为起点 任意一点味结束的多边形的面积 在询问的时候 只需要求出询问的点还有第一个点这个三角形的面积 加上预处理的从第一个点到给的第一个点的多边形面积 加上总面积减去第一个点到给的第二个点的多边形面积 就是一个多边形面积 用总面积一件就是另一个多边形的面积 取一个较小的就是答案了
代码如下
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
struct point
{
double x,y;
}p[50030];
double area[50030];
double getarea(int a,int b)
{
return abs(p[0].x*p[a].y+p[a].x*p[b].y+p[b].x*p[0].y-p[0].y*p[a].x-p[a].y*p[b].x-p[b].y*p[0].x);
}
int main()
{
int n,m;
while (scanf("%d%d",&n,&m)!=EOF)
{
memset(area,0,sizeof(area));
for (int i=0;i<n;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
for (int i=2;i<n;i++)
{
area[i]+=area[i-1]+getarea(i,i-1);
}
double tol=0.5*area[n-1],res;
for (int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
res=abs(tol+0.5*area[a]-0.5*area[b]+0.5*getarea(a,b));
printf("%.1lf\n",min(res,tol-res));
}
}
}