Submission #64791


ソースコード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <cmath>
#include <vector>
#include <iostream>
#include <algorithm>
#include <set>
#include <iomanip>
#include <queue>
#include <string>
#include <map>
#include <fstream>
#include <cassert>
#include <stack>
#include <climits>
#include <array>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include <functional>
#include <cfloat>
#include <numeric>
#include <random>
#include <sstream>
#include <bitset>
using namespace std;
const double PI = std::acos(-1);
static double radius;
struct Angle {
double sin, cos;
static Angle from_cos(const double cos) {
return Angle{ std::sqrt(1 - cos * cos), cos };
}
static Angle from_sin(const double sin) {
return Angle{ sin, std::sqrt(1 - sin * sin) };
}
double radian() const {
return (sin >= 0) ? std::acos(cos) : 2 * PI - std::acos(cos);
}
Angle operator+(const Angle other) const {
return Angle{ sin * other.cos + cos * other.sin, cos * other.cos - sin * other.sin };
}
Angle operator-() const {
return Angle{ -sin, cos };
}
};
struct Vector {
double dx, dy;
double cross(const Vector other) const {
return dx * other.dy - dy * other.dx;
}
double dot(const Vector other) const {
return dx * other.dx + dy * other.dy;
}
double length() const {
return std::sqrt(dx * dx + dy * dy);
}
Angle angle_to(const Vector other) const {
const auto len = length() * other.length();
return Angle{ cross(other) / len, dot(other) / len };
}
Vector rotate(const Angle angle) const {
return Vector{ dx * angle.cos - dy * angle.sin, dy * angle.cos + dx * angle.sin };
}
Vector change_length(const double new_length) const {
const auto ratio = new_length / length();
return Vector{ dx * ratio, dy * ratio };
}
};
struct Point {
double x, y;
Vector diff_to(const Point to) const {
return Vector{ to.x - x, to.y - y };
}
Point move(const Vector other) const {
return Point{ x + other.dx, y + other.dy };
}
double distance(const Point other) const {
return diff_to(other).length();
}
};
double area() {
return radius * radius * PI;
}
double intersect(const Point a, const Point b) {
const auto dist = a.distance(b);
if (dist >= radius * 2) return 0;
const auto angle_half = Angle::from_cos(dist / 2 / radius);
const auto base = a.diff_to(b).change_length(radius);
const auto angle = angle_half + angle_half;
const auto triangle = angle.sin * radius * radius;
const auto piece = angle.radian() / PI * area();
return piece - triangle;
}
std::vector<Point> cross_point(const Point a, const Point b) {
const auto dist = a.distance(b);
if (dist >= radius * 2) return {};
const auto angle = Angle::from_cos(dist / 2 / radius);
const auto base = a.diff_to(b).change_length(radius);
return { a.move(base.rotate(angle)), a.move(base.rotate(-angle)) };
}
double union_type1(const Point a, const Point b, const Point c) {
return area() * 3 - intersect(b, c) - intersect(c, a);
}
double triangle_area(const std::vector<Point> points) {
assert(points.size() == 3);
double sum{ 0 };
std::vector<double> edges;
for (auto i = 0; i < 3; ++i) {
const auto dist = points[i].distance(points[(i + 1) % 3]);
edges.push_back(dist);
const auto angle_half = Angle::from_sin(dist / 2 / radius);
const auto angle = angle_half + angle_half;
sum += area() * angle.radian() / 2 / PI - angle.sin * radius * radius / 2;
}
const auto s = std::accumulate(edges.begin(), edges.end(), 0.0) / 2;
return sum + std::sqrt(s * (s - edges[0]) * (s - edges[1]) * (s - edges[2]));
}
double union_type0(const Point a, const Point b, const Point c) {
std::vector<Point> inner_point;
for (const auto p : cross_point(a, b)) {
if (p.distance(c) < radius) {
inner_point.push_back(p);
}
}
for (const auto p : cross_point(b, c)) {
if (p.distance(a) < radius) {
inner_point.push_back(p);
}
}
for (const auto p : cross_point(c, a)) {
if (p.distance(b) < radius) {
inner_point.push_back(p);
}
}
if (inner_point.size() == 3) return area() * 3 - intersect(a, b) - intersect(b, c) - intersect(c, a) + triangle_area(inner_point);
else return area() * 3 - intersect(a, b) - intersect(b, c) - intersect(c, a);
}
double solve(const std::vector<Point> points) {
for (auto i = 0; i < 3; ++i) {
int count{ 0 };
for (const auto p : cross_point(points[(i + 1) % 3], points[(i + 2) % 3])) {
if (points[i].distance(p) < radius) {
++count;
}
}
if (count == 2) {
return union_type1(points[(i + 1) % 3], points[(i + 2) % 3], points[i]);
}
}
return union_type0(points[0], points[1], points[2]);
}
int main() {
std::cin >> radius;
std::vector<Point> points(3);
for (auto& p : points) std::cin >> p.x >> p.y;
std::cout << std::setprecision(15) << std::fixed << solve(points) << '\n';
}

ステータス

項目 データ
問題 1459 - 柿の実
ユーザー名 syoribu
投稿日時 2020-11-20 12:29:33
言語 C++17
状態 Accepted
得点 11
ソースコード長 4877 Byte
最大実行時間 26 ms
最大メモリ使用量 740 KB

セット

セット 得点 Cases
1 ALL 11 / 11 *

テストケース

ファイル名 状態 実行時間 メモリ使用量 #
in1 AC 23 ms 604 KB
1
in2 AC 17 ms 432 KB
1
in3 AC 21 ms 580 KB
1
in4 AC 21 ms 548 KB
1
in5 AC 17 ms 640 KB
1
in6 AC 24 ms 608 KB
1
in7 AC 23 ms 576 KB
1
in8 AC 24 ms 552 KB
1
in9 AC 18 ms 524 KB
1
in10 AC 24 ms 704 KB
1
in11 AC 21 ms 548 KB
1
in12 AC 23 ms 520 KB
1
in13 AC 25 ms 620 KB
1
in14 AC 15 ms 592 KB
1
in15 AC 20 ms 436 KB
1
in16 AC 16 ms 408 KB
1
in17 AC 24 ms 640 KB
1
in18 AC 21 ms 740 KB
1
in19 AC 25 ms 588 KB
1
in20 AC 23 ms 532 KB
1
in21 AC 16 ms 624 KB
1
in22 AC 26 ms 468 KB
1
in23 AC 21 ms 568 KB
1
in24 AC 21 ms 536 KB
1
in25 AC 18 ms 636 KB
1
in26 AC 17 ms 604 KB
1