P1452 [USACO03FALL] Beauty Contest G /【模板】旋转卡壳 - 洛谷
求凸包的直径.
求凸包后, 枚举边, 找到最远的点, 计算点到直线的距离.
代码
| C++ |
|---|
| { 计算几何基础 }
{ 二维凸包 }
Tdouble RoatingCalipers(const vector<Point> &p) {
if (p.size() == 3) return (p[0] - p[1]).length();
int cur = 0, len = p.size();
Tdouble ans = 0;
for (int i = 0 ; i < len - 1 ; i++) {
Line line(p[i], p[i + 1]);
while (sgn(distanceLine(p[cur], line) - distanceLine(p[(cur + 1) % len], line)) <= 0) {
cur = (cur + 1) % len;
}
ans = max({ans, (p[i] - p[cur]).length(), (p[i + 1] - p[cur]).length()});
}
return ans;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
vector<Point> a(n);
for (int i = 0 ; i < n ; i++) {
cin >> a[i];
}
auto c = ConvexHull2D(a);
auto d = RoatingCalipers(c);
cout << int(d * d);
return 0;
}
|
P3187 [HNOI2007] 最小矩形覆盖 - 洛谷
求覆盖 \(n\) 个点且面积最小的矩形, 以及该矩形的四个顶点
代码
| C++ |
|---|
| { 计算几何基础 }
{ 二维凸包 }
#define func(a) (sgn(a) < 0 ? a = -a : 0.0)
pair<array<Point, 4>, Tdouble> RoatingCalipers(const vector<Point> &p) {
Tdouble res, ans = 1e100;
int a = 1, b = 1, c = 1, len = p.size();
array<Point, 4> point;
for (int i = 1 ; i < len ; i++) {
Vector v1 = p[i - 1] - p[i], v2 = p[i] - p[i - 1];
while (sgn(cross(p[(a + 1) % len] - p[i], v1) - cross(p[a] - p[i], v1) >= 0)) {
a = (a + 1) % len;
}
while (sgn(dot(p[(b + 1) % len] - p[i], v1) - dot(p[b] - p[i], v1)) <= 0) {
b = (b + 1) % len;
}
if (i == 1) c = a;
while (sgn(dot(p[(c + 1) % len] - p[i - 1], p[i] - p[i - 1]) - dot(p[c] - p[i - 1], p[i] - p[i - 1])) <= 0) {
c = (c + 1) % len;
}
Tdouble dis = v2.length();
Tdouble L = dot(p[c] - p[i], v1) / dis;
Tdouble R = dot(p[b] - p[i - 1], v2) / dis;
Tdouble H = fabs(area2(p[i], p[i - 1], p[a])) / dis;
func(L);func(R);func(H);
res = (L + R - dis) * H;
if (res < ans) {
ans = res;
point[0] = p[i] - v2 * (L / dis);
point[1] = point[0] + v2 * ((L + R - dis) / dis);
point[2] = point[1] + (p[b] - point[1]) * (H / (p[b] - point[1]).length());
point[3] = point[2] + v1 * ((L + R - dis) / dis);
}
}
return {point, ans};
}
#undef func(a)
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
vector<Point> a(n);
for (int i = 0 ; i < n ; i++) {
cin >> a[i];
}
auto c = ConvexHull2D(a);
auto [point, ans] = RoatingCalipers(c);
cout << fixed << setprecision(5) << ans << "\n";
int pos = 0;
for (int i = 0 ; i < 4 ; i++) {
if (point[i].y < point[pos].y || (point[i].y == point[pos].y && point[i].x < point[pos].x)) {
pos = i;
}
}
for (int i = 0 ; i < 4 ; i++) {
int k = (pos + i) % 4;
if (sgn(point[k].x) == 0) point[k].x = 0.0;
if (sgn(point[k].y) == 0) point[k].y = 0.0;
cout << point[k] << "\n";
}
return 0;
}
|