牛客练习赛36-F:Rabbit的蛋糕(计算几何)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/85864172

链接:https://ac.nowcoder.com/acm/contest/328/F

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
Special Judge, 64bit IO Format: %lld
题目描述
Rabbit和xxx获得了一个很大的蛋糕,这个蛋糕实际上是由N个点组成的凸多边形(点从1到N编号,保证没有三点共线)。
接着两个人开始分蛋糕,他们准备沿着蛋糕上两点连成的直线把蛋糕切成两份,由于Rabbit是女生,xxx总会把大的那一份分给Rabbit。现在有Q种切的方案,xxx可以选择任意一种,问xxx最多能分得多少蛋糕?
输入描述:
第一行两个整数N,Q。
接下来N行,每行两个数 x i y i x_i,y_i 表示第i个点的坐标(点按逆时针顺序给出)。
接下来Q行,每行两个整数S,T表示切的两个点。
输出描述:
输出xxx最多能分得多少面积的蛋糕。
示例1
输入
4 2
0.5 0.5
10.5 0.5
10.5 10.5
0.5 10.5
1 3
4 2
输出
50.00
备注:
3 < = n < = 1 0 5 3<=n<=10^5
1 < = q < = 1 0 5 1<=q<=10^5
1 0 5 < = x i , y i < = 1 0 5 −10^5<=x_i,y_i<=10^5
1 < = S , T < = N S ! = T 1<=S,T<=N,S!=T
本题采用special judge,假设你的答案为a,标程答案为b,如果满足 a b m a x ( 1 , b ) 1 0 4 \frac{|a−b|}{max(1,|b|)}≤10^{−4} ,则认为是正确的。
思路:计算S,T两点连线分割多边形所得到的某一半的面积,可以利用叉积来求,从S点开始遍历到T点,即: A r e a = i = S + 1 T ( x i x s ) ( y i 1 y s ) ( x i 1 x s ) ( y i y s ) Area=\sum_{i=S+1}^{T} (x_i-x_s)(y_{i-1}-y_s)-(x_{i-1}-x_s)(y_i-y_s)
化简可得: A r e a = i = S + 1 T x i y i 1 x i 1 y i + x s ( y i y i 1 ) + y s ( x i 1 x i ) Area=\sum_{i=S+1}^{T} x_iy_{i-1}-x_{i-1}y_i+x_s(y_i-y_{i-1})+y_s(x_{i-1}-x_i)
然后就可以用前缀和记录了,遍历的时候再求答案即可。

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+10;
const int MOD=1e9+7;
typedef long long ll;
struct Point{double x,y;}p[MAX];
struct lenka{int s,t;}a[MAX];
Point operator-(Point A,Point B){return (Point){A.x-B.x,A.y-B.y};}
double operator^(Point A,Point B){return A.x*B.y-A.y*B.x;}
double Polyarea(Point *p,int n)
{
	double area=0;
	for(int i=1;i<n-1;i++)area+=(p[i]-p[0])^(p[i+1]-p[0]);
	return fabs(area);
}
double A[MAX];
double B[MAX];
double sum[MAX];
int main()
{
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
    for(int i=0;i<m;i++)scanf("%d%d",&a[i].s,&a[i].t);
    memset(A,0,sizeof A);
    memset(B,0,sizeof B);
    memset(sum,0,sizeof sum);
    for(int i=1;i<n;i++)
    {
        sum[i]=sum[i-1]+(p[i]^p[i-1]);
        A[i]=A[i-1]+p[i].y-p[i-1].y;
        B[i]=B[i-1]+p[i-1].x-p[i].x;
    }
    double ans=0,area=Polyarea(p,n);
    for(int i=0;i<m;i++)
    {
        int L=min(a[i].s-1,a[i].t-1);
        int R=max(a[i].s-1,a[i].t-1);
        double now=fabs(sum[R]-sum[L]+p[L].x*(A[R]-A[L])+p[L].y*(B[R]-B[L]));
        ans=max(ans,min(now,area-now));
    }
    printf("%.10f\n",ans/2.0);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/85864172
今日推荐