QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#124282 | #3139. Largest Quadrilateral | GoatGirl98 | WA | 2ms | 3236kb | C++14 | 6.3kb | 2023-07-14 16:32:12 | 2023-07-14 16:32:13 |
Judging History
answer
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <functional>
#include <algorithm>
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: 100
Accepted
time: 1ms
memory: 3100kb
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:
3 6 0
result:
ok 3 lines
Test #2:
score: 0
Accepted
time: 1ms
memory: 3136kb
input:
1 4 0 0 1 0 0 1 3 2
output:
2.5
result:
ok single line: '2.5'
Test #3:
score: 0
Accepted
time: 1ms
memory: 3008kb
input:
3 4 0 0 0 0 0 0 0 0 5 0 0 1 0 3 1 1 2 0 1 4 0 0 4 0 0 4 1 1
output:
0 3 6
result:
ok 3 lines
Test #4:
score: 0
Accepted
time: 1ms
memory: 3184kb
input:
3 4 0 0 1 1 2 2 1 1 5 0 0 3 3 1 1 4 4 2 2 6 0 0 0 4 4 0 0 0 1 1 1 2
output:
0 0 8
result:
ok 3 lines
Test #5:
score: -100
Wrong Answer
time: 2ms
memory: 3236kb
input:
3 6 0 0 8 8 7 9 6 9 5 8 0 99 29 999891293 708205 369022896 771 993004062 999827531 929592437 29458 994968624 999539287 569046020 1943 2200 986643253 11189 5792636 712825 999917190 2482686 272282 43058 665660 10373878 31825 508452623 112 3304 269412577 43817590 3789 999996618 957802194 999902626 9749...
output:
388 996775018731291776 965005706567704576
result:
wrong answer 2nd lines differ - expected: '996775018731291724.5', found: '996775018731291776'