题目链接:https://codeforces.com/contest/772/problem/B
题意:按顺序给出凸多边形的顶点,每个顶点都可以在区间[0,D]里任意移动,移动完之后使得这个图形还是一个凸多边形,求出最大的D值。
题解:看图,显然答案为
代码:
# define _CRT_SECURE_NO_WARNINGS
#include <iomanip>
#pragma GCC optimize(2)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#define Pair pair<int,int>
//#define int long long
#define fir first
#define sec second
namespace fastIO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
//fread->read
bool IOerror = 0;
//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
inline char nc() {
static char buf[BUF_SIZE], * p1 = buf + BUF_SIZE, * pend = buf + BUF_SIZE;
if (p1 == pend) {
p1 = buf; pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if (pend == p1) { IOerror = 1; return -1; }
}
return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
template<class T> inline bool read(T& x) {
bool sign = 0; char ch = nc(); x = 0;
for (; blank(ch); ch = nc());
if (IOerror)return false;
if (ch == '-')sign = 1, ch = nc();
for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0';
if (sign)x = -x;
return true;
}
inline bool read(double& x) {
bool sign = 0; char ch = nc(); x = 0;
for (; blank(ch); ch = nc());
if (IOerror)return false;
if (ch == '-')sign = 1, ch = nc();
for (; ch >= '0' && ch <= '9'; ch = nc())x = x * 10 + ch - '0';
if (ch == '.') { double tmp = 1; ch = nc(); for (; ch >= '0' && ch <= '9'; ch = nc())tmp /= 10.0, x += tmp * (ch - '0'); }
if (sign)x = -x; return true;
}
inline bool read(char* s) {
char ch = nc();
for (; blank(ch); ch = nc());
if (IOerror)return false;
for (; !blank(ch) && !IOerror; ch = nc())* s++ = ch;
*s = 0;
return true;
}
inline bool read(char& c) {
for (c = nc(); blank(c); c = nc());
if (IOerror) { c = -1; return false; }
return true;
}
template<class T, class... U>bool read(T& h, U& ... t) { return read(h) && read(t...); }
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;
using namespace std;
/*---------------------------------------------------------------------------------------------------------------------------*/
const double eps = 1e-10;
struct Point { double x, y; Point(double x = 0, double y = 0) :x(x), y(y) {} };
typedef Point Vector;
Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator - (Point A, Point B) { return Vector(A.x - B.x, A.y - B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x * p, A.y * p); }
Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); }
bool operator < (const Point& A, const Point& B) { return A.x < B.x || (A.x == B.x && A.y < B.y); }
int dcmp(double x) { if (fabs(x) < eps)return 0; else return x < 0 ? -1 : 1; }
bool operator == (const Point& A, const Point& B) { return dcmp(A.x - B.x) == 0 && dcmp(A.y - B.y) == 0; }
double Dot(Vector A, Vector B) { return A.x * B.x + A.y * B.y; }
double Length(Vector A) { return sqrt(Dot(A, A)); }
double Dist2(const Point& A, const Point& B) { return (A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y); }
double Dist(const Point& A, const Point& B) { return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y)); }
double Angle(Vector A, Vector B) { return acos(Dot(A, B) / Length(A) / Length(B)); }
double Cross(Vector A, Vector B) { return A.x * B.y - A.y * B.x; }
double Area2(Point A, Point B, Point C) { return Cross(B - A, C - A); }
double DistanceToLine(Point P, Point A, Point B) { Vector v1 = B - A, v2 = P - A; return fabs(Cross(v1, v2)) / Length(v1); }
Vector Normal(Vector A) { double L = Length(A); return Vector(-A.y / L, A.x / L); }
Vector Rotate(Vector A, double rad) { return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad)); }
Point GetLineIntersection(Point P, Vector v, Point Q, Vector w) { Vector u = P - Q; double t = Cross(w, u) / Cross(v, w); return P + v * t; }
double PolygonArea(vector<Point>p) {//duo area
double area = 0;
int n = p.size();
for (int i = 1; i < n - 1; i++)area += Cross(p[i] - p[0], p[i + 1] - p[0]);
return area / 2;
}
double torad(double deg) { return deg / 180 * acos(-1); }
vector<Point> ConvexHull(vector<Point>& p) {
sort(p.begin(), p.end());
p.erase(unique(p.begin(), p.end()), p.end());
int n = p.size();
int m = 0;
vector<Point> ch(n + 1);
for (int i = 0; i < n; i++) { while (m > 1 && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)m--; ch[m++] = p[i]; }
int k = m;
for (int i = n - 2; i >= 0; i--) { while (m > k && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0)m--; ch[m++] = p[i]; }
if (n > 1)m--;
ch.resize(m);
return ch;
}
double diameter2(vector<Point>& points) {
vector<Point>p = ConvexHull(points);
int n = p.size();
if (n == 1) return 0;
if (n == 2) return Dist2(p[0], p[1]);
//p.push_back(p[0]); // 免得取模
double ans = 0;
for (int u = 0, v = 1; u < n; u++) {
for (;;) {
//Cross(p[u+1]-p[u],p[v+1]-p[v])<=0时停止旋转
int diff = Cross(p[u + 1] - p[u], p[v + 1] - p[v]);
if (diff <= 0) {
ans = max(ans, Dist2(p[u], p[v])); // u和v是对踵点
if (diff == 0) ans = max(ans, Dist2(p[u], p[v + 1])); // diff == 0时u和v+1也是对踵点
break;
}
v = (v + 1) % n;
}
}
return ans;
}
Point PolygonCenter(vector<Point>p) {
Point ans(0, 0);
int n = p.size();
if (PolygonArea(p) == 0)return ans;
for (int i = 0; i < n; i++) {
ans = ans + (p[i] + p[(i + 1) % n]) * Cross(p[i], p[(i + 1) % n]);
}
return ans / PolygonArea(p) / 6.0;
}
/*---------------------------------------------------------------------------------------------------------------------------*/
struct Line {
Point P;
Vector v;
double ang;
Line() {}
Line(Point P, Vector v) :P(P), v(v) { ang = atan2(v.y, v.x); }
bool operator < (const Line& L)const {
return ang < L.ang;
}
};
Point GetLineIntersection(const Line& a, const Line& b) {
Vector u = a.P - b.P;
double t = Cross(b.v, u) / Cross(a.v, b.v);
return a.P + a.v * t;
}
bool OnLeft(Line L, Point p) { return Cross(L.v, p - L.P) > 0; }
vector<Point>HalfplaneIntersection(vector<Line>L) {
int n = L.size();
sort(L.begin(), L.end());
int first, last;
vector<Point> p(n);
vector<Line> q(n);
vector<Point> ans;
q[first = last = 0] = L[0];
for (int i = 1; i < n; i++) {
while (first < last && !OnLeft(L[i], p[last - 1])) last--;
while (first < last && !OnLeft(L[i], p[first]))first++;
q[++last] = L[i];
if (fabs(Cross(q[last].v, q[last - 1].v)) < eps) {
last--;
if (OnLeft(q[last], L[i].P))q[last] = L[i];
}
if (first < last)p[last - 1] = GetLineIntersection(q[last - 1], q[last]);
}
while (first < last && !OnLeft(q[first], p[last - 1]))last--;//删除无用平面
if (last - first <= 1)return ans;
p[last] = GetLineIntersection(q[last], q[first]);//计算首尾两个半平面的交点
//从deque复制到输出中
for (int i = first; i <= last; i++)ans.push_back(p[i]);
return ans;
}
bool OnSegment(const Point& p, const Point& a1, const Point& a2) {
return dcmp(Cross(a1 - p, a2 - p)) == 0 && dcmp(Dot(a1 - p, a2 - p)) < 0;
}
bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2) {
double c1 = Cross(a2 - a1, b1 - a1), c2 = Cross(a2 - a1, b2 - a1),
c3 = Cross(b2 - b1, a1 - b1), c4 = Cross(b2 - b1, a2 - b1);
return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
}
int IsPointInPolygon(const Point& p, const vector<Point>& poly) {
int wn = 0;
int n = poly.size();
for (int i = 0; i < n; i++) {
const Point& p1 = poly[i];
const Point& p2 = poly[(i + 1) % n];
if (p1 == p || p2 == p || OnSegment(p, p1, p2)) return -1; // 在边界上
//if (dcmp(dists(p, p1, p2)) == 0) return 0;
int k = dcmp(Cross(p2 - p1, p - p1));
int d1 = dcmp(p1.y - p.y);
int d2 = dcmp(p2.y - p.y);
if (k > 0 && d1 <= 0 && d2 > 0) wn++;
if (k < 0 && d2 <= 0 && d1 > 0) wn--;
}
if (wn != 0) return 1; // 内部
return 0; // 外部
}
bool ConvexPolygonDisjoint(const vector<Point> ch1, const vector<Point> ch2) {
int c1 = ch1.size();
int c2 = ch2.size();
cout << "c1 " << c1 << " " << "c2 " << c2 << endl;
for (int i = 0; i < c1; i++)
if (IsPointInPolygon(ch1[i], ch2) != 0) return false; // 内部或边界上
for (int i = 0; i < c2; i++)
if (IsPointInPolygon(ch2[i], ch1) != 0) return false; // 内部或边界上
for (int i = 0; i < c1; i++)
for (int j = 0; j < c2; j++)
if (SegmentProperIntersection(ch1[i], ch1[(i + 1) % c1], ch2[j], ch2[(j + 1) % c2])) return false;
return true;
}
/*---------------------------------------------------------------------------------------------------------------------------*/
struct Circle {
Point c;
double r;
Circle(Point c, double r) :c(c), r(r) {}
Point point(double a) {
return Point(c.x + cos(a) * r, c.y + sin(a) * r);
}
};
double angle(Vector v) { return atan2(v.y, v.x); }
int getCircleCircleIntersection(Circle C1, Circle C2, vector<Point>& sol) {
double d = Length(C1.c - C2.c);
if (dcmp(d) == 0) { //首先圆心要重合
if (dcmp(C1.r - C2.r) == 0) return -1; //其次半径要相同,然后就可以推出两圆重合
return 0;
}
if (dcmp(C1.r + C2.r - d) < 0) return 0; //相离没交点
if (dcmp(fabs(C1.r - C2.r) - d) > 0) return 0; //圆在圆中,没有交点
double a = angle(C2.c - C1.c); //向量C1C2的极角
double da = acos((C1.r * C1.r + d * d - C2.r * C2.r) / (2 * C1.r * d)); //C1C2到C1P1的角
Point p1 = C1.point(a - da), p2 = C1.point(a + da);
sol.push_back(p1);
if (p1 == p2) return 1; //相切
sol.push_back(p2);
return 2; //相交
}
bool isInCircle(Point p, Circle cir) {
return dcmp(Dist2(p, cir.c) - cir.r * cir.r) < 0;
}
bool check(vector<Point>p, vector<Circle>cir) {
if (p.empty()) return true;
for (int i = 0; i < p.size(); i++) {
bool ok = true;
Point tp = Point(-p[i].x, -p[i].y);
for (int j = 1; j < cir.size(); j++)
if (isInCircle(tp, cir[j])) { ok = false; break; }
if (ok)return true;
}
return false;
}
/*---------------------------------------------------------------------------------------------------------------------------*/
const int N = 1e6 + 100;
const double pi = acos(-1.0);
typedef long long ll;
//const int mod = 998244353;
const int mod = 1e9 + 7;
#define inf 0x3f3f3f3f
struct ship {
double x, y, step;
ship(double x, double y, double step) :x(x), y(y), step(step) {}
};
struct thing {
int num, period, time;
bool operator < (const thing& y)const {
return y.time < time || (y.time == time && y.num < num);
}
thing() {}
thing(int num, int period, int time) :num(num), period(period), time(time) {}
};
signed main() {
int n;
cin >> n;
vector<Point>p;
for (int i = 0; i < n; i++) {
double x, y;
cin >> x >> y;
p.push_back(Point(x, y));
}
double res = 1e9;
for (int i = 0; i < n; i++) {
if (i == 0)res = min(res, DistanceToLine(p[i], p[1], p[n - 1])/2.0);
else if (i == n - 1)res = min(res, DistanceToLine(p[i], p[0], p[n - 2])/2.0);
else res = min(res, DistanceToLine(p[i], p[i - 1], p[i + 1])/2.0);
}
cout <<setprecision(10) << res << endl;
return 0;
}
题目描述:
You are given a convex polygon P with n distinct vertices p1, p2, ..., pn. Vertex pi has coordinates (xi, yi) in the 2D plane. These vertices are listed in clockwise order.
You can choose a real number D and move each vertex of the polygon a distance of at most D from their original positions.
Find the maximum value of D such that no matter how you move the vertices, the polygon does not intersect itself and stays convex.
Input
The first line has one integer n (4 ≤ n ≤ 1 000) — the number of vertices.
The next n lines contain the coordinates of the vertices. Line i contains two integers xi and yi ( - 109 ≤ xi, yi ≤ 109) — the coordinates of the i-th vertex. These points are guaranteed to be given in clockwise order, and will form a strictly convex polygon (in particular, no three consecutive points lie on the same straight line).
Output
Print one real number D, which is the maximum real number such that no matter how you move the vertices, the polygon stays convex.
Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.
Namely, let's assume that your answer is a and the answer of the jury is b. The checker program will consider your answer correct if .