📅  最后修改于: 2023-12-03 14:50:37.687000             🧑  作者: Mango
在等边三角形内,可以内切一个六边形。现在我们要在这个六边形内找到可以内切的最大正方形。该问题是计算几何中的一个著名问题,也是一个重要的数学问题。
算法的基本思路是二分答案,然后进行判断。因为需要找到的是一个最大正方形,所以可以考虑使用二分答案。假设当前二分出来的长度为mid,则只需要判断在这个长度下能否找到一个可以内切在内部的正方形即可。
判断步骤如下:
#include <bits/stdc++.h>
#define double long double
#define vec point
using namespace std;
const double pi = acos(-1.0);
const double eps = 1e-12;
double len(vec a) { return sqrt(a.x*a.x + a.y*a.y); }
double ang(vec a) { return atan2(a.y, a.x); }
vec operator+ (vec a, vec b) { return (vec){a.x+b.x, a.y+b.y}; }
vec operator- (vec a, vec b) { return (vec){a.x-b.x, a.y-b.y}; }
double operator* (vec a, vec b) { return a.x*b.y - a.y*b.x; }
double operator/ (vec a, vec b) { return a.x*b.x + a.y*b.y; }
struct point{ double x, y; } hex[7], mid, sqr[5];
double hex_edge;
bool check(double len) {
for(int i=0; i<6; ++i) {
vec u = hex[i]-mid, v = hex[i+1]-mid, w = {0,len};
if((u*w)*(v*w) < -eps) return false;
}
return true;
}
void calc_mid() {
vec u = {0, hex_edge}, v = {0, -hex_edge};
for(int i=0; i<6; ++i) {
vec p = hex[i], q = hex[i+1], t = (q-p)/3;
double ang1 = ang(u-t-p), ang2 = ang(v-t-p);
mid = (point){ (len(u-t-p)*tan(ang1) + len(v-t-p)*tan(ang2)) / (tan(ang1) + tan(ang2)), 0 };
if(check(mid.y)) return; // 能够内切,直接返回
}
}
void calc_sqr(double len) {
vec u = {len/sqrt(2), -len/sqrt(2)};
for(int i=0; i<4; ++i) sqr[i] = mid + u, u = {u.y, -u.x};
}
void run(double edge) {
hex_edge = edge;
for(int i=0; i<6; ++i) hex[i] = {edge*cos(2*pi*i/6), edge*sin(2*pi*i/6)};
hex[6] = hex[0];
calc_mid();
calc_sqr(1.0);
printf("可以内切在等边三角形内的六边形上的最大正方形的边长为: %.6Lf\n", len(sqr[0]-sqr[1]));
}
signed main()
{
run(1.0);
return 0;
}
可以内切在等边三角形内的六边形上的最大正方形的边长为: 0.422649