当前位置: 首页 > news >正文

【计算几何】Largest Quadrilateral

来源:https://codeforces.com/gym/102460 的L题
这道题和 https://www.luogu.com.cn/problem/P4166 是一样的思路,不过要注意凸包中只有三个点的情况,如果有点和三角形重合,三角形和这个重合的点连起来就是四边形了,此时的最大面积就是三角形的面积。
如果没有,就固定凸包这三个点,去遍历剩余的点,取最小值即可。

#include <bits/stdc++.h>// from: cpp.json
#define INF 8e18
#define int long long
using namespace std;// 几何模板
template<class T>
struct Point {T x; T y; Point(const T &x_ = 0, const T &y_ = 0) : x(x_), y(y_) {}template<class U>operator Point<U>() const {return Point<U>(U(x), U(y));}Point &operator+=(const Point &p) & {x += p.x;y += p.y;return *this;}Point &operator-=(const Point &p) & {x -= p.x;y -= p.y;return *this;}Point &operator*=(const T &v) & {x *= v;y *= v;return *this;}Point &operator/=(const T &v) & {x /= v;y /= v;return *this;}Point operator-() const {return Point(-x, -y);}friend Point operator+(Point a, const Point &b) {return a += b;}friend Point operator-(Point a, const Point &b) {return a -= b;}friend Point operator*(Point a, const T &b) {return a *= b;}friend Point operator/(Point a, const T &b) {return a /= b;}friend Point operator*(const T &a, Point b) {return b *= a;}friend bool operator==(const Point &a, const Point &b) {return a.x == b.x && a.y == b.y;}friend bool operator<(Point a, Point b) {return a.x == b.x ? a.y < b.y : a.x < b.x;}friend std::istream &operator>>(std::istream &is, Point &p) {return is >> p.x >> p.y;}friend std::ostream &operator<<(std::ostream &os, const Point &p) {return os << "(" << p.x << ", " << p.y << ")";}
};template<class T>
T cross(const Point<T> &a, const Point<T> &b) {return a.x * b.y - a.y * b.x;
}template<class T>
T cross3(const Point<T> &a, const Point<T> &b, const Point<T> &c) {return cross(b - a, c - a);
}using LD = long double;    
using P = Point<int>;       
const LD PI = acos(-1);constexpr LD eps = 0;      vector<P> convexHull(vector<P> points) {int n = points.size();if (n <= 1) {return points;}sort(points.begin(), points.end(), [](auto &a, auto &b) {if (a.x != b.x) return a.x < b.x;return a.y < b.y;});points.erase(unique(points.begin(), points.end()), points.end());n = points.size();if (n <= 1) {return points;}bool alline = true;for (int i = 2; i < n; i++) {if (cross(points[1] - points[0], points[i] - points[0]) != 0) {alline = false;break;}}if (alline) {return {points.front(), points.back()};}vector<P> lower, upper;for (const auto &p : points) {while (lower.size() >= 2) {int m = lower.size();P a = lower[m - 2];P b = lower[m - 1];if (cross(b - a, p - b) <= 0) {lower.pop_back();} else {break;}}lower.push_back(p);}for (int i = n - 1; i >= 0; i--) {auto p = points[i];while (upper.size() >= 2) {int m = upper.size();P a = upper[m - 2];P b = upper[m - 1];if (cross(b - a, p - b) <= 0) {upper.pop_back();} else {break;}}upper.push_back(p);}lower.pop_back();upper.pop_back();lower.insert(lower.end(), upper.begin(), upper.end());return lower;
}void solve() {int n;cin >> n;vector<P> pts(n);for (int i = 0; i < n; i++) {cin >> pts[i];}if (n < 4) {cout << "0\n";return;}auto hull = convexHull(pts);if (hull.size() <= 2) {cout << "0\n";return;}if (hull.size() == 3) {bool ok = false;P A = hull[0], B = hull[1], C = hull[2];int cnta = 0, cntb = 0, cntc = 0;int S_tri = cross(B - A, C - A);int delta = INF;for (auto &p : pts) {if (p == A || p == B || p == C) {if (p == A) {cnta++;if (cnta > 1) {ok = true;break;}} else if (p == B) {cntb++;if (cntb > 1) {ok = true;break;}} else {cntc++;if (cntc > 1) {ok = true;break;}}continue;}int d1 = cross(B - A, p - A);int d2 = cross(C - B, p - B);int d3 = cross(A - C, p - C);delta = min(delta, min({d1, d2, d3}));}if (ok) {if (S_tri & 1) {cout << S_tri / 2 << ".5\n";} else {cout << S_tri / 2 << '\n';}return;} if (delta < (int) INF) {int d = S_tri - delta;if (d & 1) {cout << d / 2 << ".5\n";} else {cout << d / 2 << '\n';}} else {cout << "0\n";}return;}int m = hull.size();    int ans = 0;for (int i = 0; i < m; i++) {int a = (i + 1) % m, b = (i + 2) % m;for (int j = (i + 2) % m; j != i; j = (j + 1) % m) {while (a != j && cross(hull[j] - hull[i], hull[(a + 1) % m] - hull[i]) < cross(hull[j] - hull[i], hull[a] - hull[i])) {a = (a + 1) % m;}while (b != i && cross(hull[j] - hull[i], hull[(b + 1) % m] - hull[i]) > cross(hull[j] - hull[i], hull[b] - hull[i])) {b = (b + 1) % m;}ans = max(ans, -cross(hull[j] - hull[i], hull[a] - hull[i]) + cross(hull[j] - hull[i], hull[b] - hull[i]));}}if (ans & 1) {cout << ans / 2 << ".5" << '\n';} else {cout << ans / 2 << '\n';}
}signed main() {ios::sync_with_stdio(false);cin.tie(nullptr);int t = 1;cin >> t;while(t--){solve();}return 0;
}
http://www.njgz.com.cn/news/26.html

相关文章:

  • 2025暑假qbxtNOIP实战梳理营Day1题目
  • 请求类型绑定响应类型
  • Untitled-1
  • AI代理性能提升实战:LangChain+LangGraph内存管理与上下文优化完整指南
  • GAIA基准测试介绍
  • 多项式全家桶(wjc)
  • 暑假qbxtNOIP实战梳理营Day1题目
  • 7月26日
  • 韦东山:嵌入式Linux全新系列教程之驱动大全(基于IMX6ULL开发板) 视频+资料(60G) 价值1299元
  • ARC200 小记
  • java第二十六天
  • 咕咕嘎嘎!!!(hard)
  • 主流PLC串口自由协议通信标准化
  • 20250726
  • Abp vNext -动态 C# API 实现原理解析
  • 健身营养——Stan Efferding
  • 20250726-31
  • Linux 如何统计系统上各个用户登录(或者登出)记录出现的次数?
  • ThreadLocal
  • linuxQT配置过程遇到的问题解决办法
  • 倍增法找LCA(最短公共祖先)
  • HTML网页基础(超文本标记语言)
  • shell学习2