Pagini recente » Cod sursa (job #196243) | Cod sursa (job #3353950) | Cod sursa (job #3345348) | Monitorul de evaluare | Cod sursa (job #3314232)
#include <array>
#include <cmath>
#include <functional>
#include <iostream>
#include <type_traits>
#include <utility>
template<typename T, std::size_t N = 2>
requires std::is_floating_point_v<T>
class Point {
std::array<T, N> x_{};
// Apply callable coordinate-wise to *this and optional others.
template<typename Predicate, typename... Points>
constexpr Point convolute(Predicate &&predicate, Points const &... that) const
noexcept(std::is_nothrow_invocable_v<Predicate, T, decltype(that[0])...>) {
Point out{};
for (std::size_t i = 0; i < N; ++i)
out[i] = std::invoke(predicate, (*this)[i], that[i]...);
return out;
}
public:
public:
// default constructor: zero initialize
constexpr Point() noexcept = default;
// Variadic constructor for exactly N arguments.
template<typename... Ts>
requires (sizeof...(Ts) == N) &&
(std::conjunction_v<std::is_convertible<Ts, T>...>) &&
(sizeof...(Ts) > 0)
constexpr explicit Point(Ts&&... args) noexcept
: x_{ static_cast<T>(std::forward<Ts>(args))... } {}
// element access
[[nodiscard]] constexpr T &operator[](std::size_t i) noexcept { return x_[i]; }
[[nodiscard]] constexpr T const &operator[](std::size_t i) const noexcept { return x_[i]; }
// ---------- arithmetic ----------
[[nodiscard]] constexpr Point operator-() const noexcept {
return convolute(std::negate<>{});
}
[[nodiscard]] constexpr Point operator+() const noexcept { return *this; }
[[nodiscard]] constexpr Point operator+(Point const &that) const noexcept {
return convolute(std::plus<>{}, that);
}
constexpr Point &operator+=(Point const &that) noexcept {
*this = *this + that;
return *this;
}
[[nodiscard]] constexpr Point operator-(Point const &that) const noexcept {
return convolute(std::minus<>{}, that);
}
constexpr Point &operator-=(Point const &that) noexcept {
*this = *this - that;
return *this;
}
[[nodiscard]] constexpr Point operator*(T k) const noexcept {
return convolute([k](T a) noexcept { return a * k; });
}
constexpr Point &operator*=(T k) noexcept {
*this = *this * k;
return *this;
}
[[nodiscard]] constexpr Point operator/(T k) const noexcept {
return convolute([k](T a) noexcept { return a / k; });
}
constexpr Point &operator/=(T k) noexcept {
*this = *this / k;
return *this;
}
[[nodiscard]] T cross(Point const &that) const noexcept
requires (N == 2) {
return (*this)[0] * that[1] - (*this)[1] * that[0];
}
friend constexpr Point operator*(T k, Point const &p) noexcept { return p * k; }
// element-wise power
[[nodiscard]] constexpr Point operator^(std::size_t exp) const noexcept {
return convolute([exp](T a) noexcept { return std::pow(a, static_cast<T>(exp)); });
}
constexpr Point &operator^=(std::size_t exp) noexcept {
*this = *this ^ exp;
return *this;
}
// ---------- utilities ----------
[[nodiscard]] constexpr Point sqrp() const noexcept {
Point out{};
for (std::size_t i = 0; i < N; ++i)
out[i] = x_[i] * x_[i];
return out;
}
// Euclidean distance
[[nodiscard]] T dist(Point const &that) const noexcept {
T sum{};
for (std::size_t i = 0; i < N; ++i) {
T d = x_[i] - that.x_[i];
sum += d * d;
}
return std::sqrt(sum);
}
// coordinate-wise absolute value
[[nodiscard]] constexpr Point abs() const noexcept {
return convolute([](T a) noexcept { return std::fabs(a); });
}
// ---------- I/O ----------
friend std::istream &operator>>(std::istream &is, Point &p) {
for (auto &d: p.x_) is >> d;
return is;
}
friend std::ostream &operator<<(std::ostream &os, Point const &p) {
for (auto const &d: p.x_) os << d << ' ';
return os;
}
};
template<typename T, std::size_t N = 2>
requires std::is_floating_point_v<T>
class Convex {
std::vector<Point<T, N> > p_;
public:
// ---- Constructors ----
Convex() = default;
explicit Convex(std::vector<Point<T, N> > pts) : p_(std::move(pts)) {
}
template<typename... Ps>
requires (sizeof...(Ps) >= 3) &&
(std::conjunction_v<std::is_convertible<Ps, Point<T, N> >...>)
explicit Convex(Ps &&... pts) : p_{std::forward<Ps>(pts)...} {
}
// ---- Basic access ----
[[nodiscard]] std::size_t size() const noexcept { return p_.size(); }
[[nodiscard]] Point<T, N> const &operator[](std::size_t i) const noexcept { return p_[i]; }
[[nodiscard]] Point<T, N> &operator[](std::size_t i) noexcept { return p_[i]; }
// ---- Centroid (geometric average) ----
[[nodiscard]] Point<T, N> inner() const noexcept {
Point<T, N> centroid{};
if (p_.empty()) return centroid;
for (auto const &pt: p_) centroid += pt;
centroid /= static_cast<T>(p_.size());
return centroid;
}
// ---- Area (2D only) ----
[[nodiscard]] T area() const noexcept
requires (N == 2) {
if (p_.size() < 3) return T{};
T a{};
for (std::size_t i = 0; i < p_.size(); ++i) {
a += p_[i].cross(p_[(i + 1) % p_.size()]);
}
return std::fabs(a) / 2;
}
// ---- I/O ----
friend std::istream &operator>>(std::istream &is, Convex &c) {
std::size_t n;
if (!(is >> n)) return is;
c.p_.resize(n);
for (auto &pt: c.p_) is >> pt;
return is;
}
friend std::ostream &operator<<(std::ostream &os, Convex const &c) {
os << c.p_.size() << '\n';
for (auto const &pt: c.p_) os << pt << '\n';
return os;
}
};
#include<bits/stdc++.h>
using namespace std;
int main() {
#ifndef LOCAL
freopen("aria.in", "r", stdin);
freopen("aria.out", "w", stdout);
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
#endif
Convex<long double> shape{};
cin >> shape;
cout << fixed << setprecision(6) << static_cast<double>(shape.area()) << '\n';
return 0;
}