QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#124294 | #3139. Largest Quadrilateral | GoatGirl98 | WA | 1ms | 3088kb | C++14 | 6.4kb | 2023-07-14 16:40:25 | 2023-07-14 16:40:27 |
Judging History
answer
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <functional>
#include <algorithm>
#define double long double
#define fabs fabsl
using namespace std;
const double INF = 1145141919810114514.0;
const double eps = 1e-9;
int sgn(double x)
{
if(fabs(x) > eps)
return x > 0 ? 1 : -1;
else
return 0;
}
struct point
{
double x, y, idx;
point(double _x = 0.0, double _y = 0.0) : x(_x), y(_y), idx(0) {}
point operator-(const point& o) const { return point(x - o.x, y - o.y); }
// cross product of vector
double operator^(const point& o) const { return x * o.y - y * o.x; }
double dis2(const point& o) const { return (x - o.x) * (x - o.x) + (y - o.y) * (y - o.y); }
double dis(const point& o) const { return sqrt(dis2(o)); }
bool operator<(const point& o) const { return sgn(x - o.x) ? (sgn(x - o.x) < 0) : (sgn(y - o.y) < 0); }
bool operator==(const point& o) const { return sgn(x - o.x) == 0 && sgn(y - o.y) == 0; }
};
struct line
{
point s, e;
line() {}
line(point _s, point _e) : s(_s), e(_e) {}
// segment only
double len() const { return s.dis(e); }
double dis_point_to_line(const point& p) const { return fabs((p - s) ^ (e - s)) / len(); }
};
// andrew
vector<point> get_convex(vector<point>& points)
{
int n = (int)points.size();
// sorted before calling this
// sort(points.begin(), points.end());
vector<int> stk;
vector<bool> used(n);
stk.push_back(0);
// upper convex
for (int i = 1; i < n; ++i)
{
while (stk.size() >= 2 && sgn((points[stk[stk.size() - 1]] - points[stk[stk.size() - 2]]) ^ (points[i] - points[stk[stk.size() - 1]])) <= 0)
used[stk.back()] = false, stk.pop_back();
used[i] = true, stk.push_back(i);
}
// stk.back() == n - 1
// lower convex
int upper_size = stk.size();
for (int i = n - 2; i >= 0; --i)
{
if (used[i])
continue;
while (stk.size() > upper_size && sgn((points[stk[stk.size() - 1]] - points[stk[stk.size() - 2]]) ^ (points[i] - points[stk[stk.size() - 1]])) <= 0)
used[stk.back()] = false, stk.pop_back();
used[i] = true, stk.push_back(i);
}
// stk.back() == stk[0]
vector<point> ret;
for (int i = 0; i < stk.size(); ++i)
ret.push_back(points[stk[i]]);
return ret;
}
double largest_quadrilateral(vector<point>& points)
{
// int n = points.size();
sort(points.begin(), points.end());
// points.erase(unique(points.begin(), points.end()), points.end());
int n = points.size();
for (int i = 0; i < n; ++i)
points[i].idx = i;
vector<point> hull = get_convex(points);
int m = hull.size() - 1;
if (m == 2) // collinear points
return 0.0;
else if (m == 3) // big triangle(hull) - small triangle(inside)
{
double triangle_area_double = fabs((hull[2] - hull[1]) ^ (hull[1] - hull[0]));
double cut_triangle_double = INF;
for (int i = 0; i < n; ++i)
{
if (points[i].idx == hull[0].idx || points[i].idx == hull[1].idx || points[i].idx == hull[2].idx)
continue;
double cut_double_1 = fabs((hull[0] - points[i]) ^ (hull[1] - points[i]));
double cut_double_2 = fabs((hull[1] - points[i]) ^ (hull[2] - points[i]));
double cut_double_3 = fabs((hull[2] - points[i]) ^ (hull[0] - points[i]));
cut_triangle_double = min(min(cut_triangle_double, cut_double_1), min(cut_double_2, cut_double_3));
}
if (sgn(INF - cut_triangle_double) == 0)
return 0.0;
else
return (triangle_area_double - cut_triangle_double) / 2.0;
}
else // rotating cliper (2 groups)
{
double ans_double = 0.0;
// Antipodal point-point (i, j) and (x, y)
int i = 0, j = 1, x = 0, y = 1;
for (; i < m; ++i)
{
while (1)
{
int flag = sgn((hull[(i + 1) % m] - hull[i]) ^ (hull[(j + 1) % m] - hull[j]));
if (flag <= 0) // (i, j) is antipodal point-point
{
line diagonal = line(hull[i], hull[j]);
while ((x + 1) % m != j && sgn(diagonal.dis_point_to_line(hull[x]) - diagonal.dis_point_to_line(hull[(x + 1) % m])) < 0)
x = (x + 1) % m;
while ((y + 1) % m != i && sgn(diagonal.dis_point_to_line(hull[y]) - diagonal.dis_point_to_line(hull[(y + 1) % m])) < 0)
y = (y + 1) % m;
ans_double = max(ans_double, diagonal.len() * (diagonal.dis_point_to_line(hull[x]) + diagonal.dis_point_to_line(hull[y])));
// corner case : (i, (i + 1) % m) parallel with (j, (j + 1) % m)
if (flag == 0)
{
j = (j + 1) % m;
diagonal = line(hull[i], hull[j]);
while ((x + 1) % m != j && sgn(diagonal.dis_point_to_line(hull[x]) - diagonal.dis_point_to_line(hull[(x + 1) % m])) <= 0)
x = (x + 1) % m;
while ((y + 1) % m != i && sgn(diagonal.dis_point_to_line(hull[y]) - diagonal.dis_point_to_line(hull[(y + 1) % m])) <= 0)
y = (y + 1) % m;
ans_double = max(ans_double, diagonal.len() * (diagonal.dis_point_to_line(hull[x]) + diagonal.dis_point_to_line(hull[y])));
j = (j + m - 1) % m;
}
break;
}
// rad : i < x < j < y
if (y == j)
y = (y + 1) % m;
j = (j + 1) % m;
}
if (x == i)
x = (x + 1) % m;
}
return ans_double / 2.0;
}
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
int n;
scanf("%d", &n);
vector<point> points(n);
for (int i = 0; i < n; ++i)
scanf("%lf%lf", &points[i].x, &points[i].y);
double ans = largest_quadrilateral(points);
if (sgn(ans - (long long)(ans + eps)) == 0)
printf("%lld\n", (long long)(ans + eps));
else
printf("%lld.5\n", (long long)(ans + eps));
}
}
詳細信息
Test #1:
score: 0
Wrong Answer
time: 1ms
memory: 3088kb
input:
3 5 0 0 1 0 3 1 1 2 0 1 4 0 0 4 0 0 4 1 1 4 0 0 1 1 2 2 1 1
output:
0 0 0
result:
wrong answer 1st lines differ - expected: '3', found: '0'