题目描述
Rabbit和xxx获得了一个很大的蛋糕,这个蛋糕实际上是由N个点组成的凸多边形(点从1到N编号,保证没有三点共线)。
接着两个人开始分蛋糕,他们准备沿着蛋糕上两点连成的直线把蛋糕切成两份,由于Rabbit是女生,xxx总会把大的那一份分给Rabbit。现在有Q种切的方案,xxx可以选择任意一种,问xxx最多能分得多少蛋糕?
输入描述:
第一行两个整数N,Q。
接下来N行,每行两个数xi,yi表示第i个点的坐标(点按逆时针顺序给出)。
接下来Q行,每行两个整数S,T表示切的两个点。
输出描述:
输出xxx最多能分得多少面积的蛋糕。
输入
4 2
0.5 0.5
10.5 0.5
10.5 10.5
0.5 10.5
1 3
4 2
输出
50.00
思路
-
暴力枚举TLE
-
记录从起点到每个点的面积,这样任意平分的面积就可以表示:
S3 = S - S1 - S2 -
叉积求面积:
#include <bits/stdc++.h>
#define LL long long
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define REP(i, n) for (int i = 1; i <= (n); ++i)
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define maxn 100005
using namespace std;
struct ac{
double x, y;
friend double operator * (const ac t1, const ac t2) {
double sum = t1.x * t2.y - t1.y * t2.x;
return abs(sum);
}
friend ac operator - (const ac t1, const ac t2) {
return {t1.x - t2.x, t1.y - t2.y};
}
}a[maxn];
int N, Q;
double pre[maxn];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
#endif
scanf("%d %d", &N, &Q);
pre[1] = pre[2] = 0;
REP (i, N) {
scanf("%lf %lf", &a[i].x, &a[i].y);
if (i >= 3) {
pre[i] = pre[i-1] + (a[1] - a[i-1]) * (a[1] - a[i]);
}
}
double ans = 0.0;
rep (i, Q) {
int S, T;
scanf("%d %d", &S, &T);
if (S > T) swap(S, T);
double sum = pre[T] - pre[S] - (a[1] - a[S]) * (a[1] - a[T]);
sum = min(sum, pre[N] - sum);
ans = max(sum, ans);
}
printf("%.10lf\n", ans / 2);
return 0;
}