题意:给你n个点的三维坐标,让你求一个点使得这个点到三个点的最大距离最小,也就是最小覆盖问题。
三分
思路:相当于对x,y,z坐标进行进行三分,找到最优解。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
struct node
{
double x, y, z;
}a[maxn];
int n;
double dis(double x, double y, double z)
{
double ret = 0;
for(int i = 0; i < n; ++i)
{
ret = max(ret, sqrt((a[i].x - x) * (a[i].x - x) + (a[i].y - y) * (a[i].y - y) + (a[i].z - z) * (a[i].z - z)));
}
return ret;
}
double slove(double c[], int num)
{
if(num >= 3)
return dis(c[0], c[1], c[2]);
double l = -1e5, r = 1e5;
double midl, midr, ans;
while(r - l > 1e-6)
{
midl = l + (r - l) / 3;
midr = r - (r - l) / 3;
c[num] = midl;
double ans1 = slove(c, num + 1);
c[num] = midr;
double ans2 = slove(c, num + 1);
if(ans1 > ans2)
{
ans = ans2;
l = midl;
}
else
{
ans = ans1;
r = midr;
}
}
return ans;
}
int main()
{
scanf("%d", &n);
for(int i = 0; i < n; ++i)
scanf("%lf%lf%lf", &a[i].x, &a[i].y, &a[i].z);
double c[4];
double ans = slove(c, 0);
printf("%.10f\n", ans);
return 0;
}
模拟退火
思路:首先不知道模拟退火的可以看看这篇文章,讲的很棒,打开链接
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e2 + 10;
struct node
{
double x, y, z;
}a[maxn];
int n;
double X, Y, Z, ans;
double dis(double x, double y, double z)
{
double ret = 0;
for(int i = 0; i < n; ++i)
{
ret = max(ret, sqrt((a[i].x - x) * (a[i].x - x) + (a[i].y - y) * (a[i].y - y) + (a[i].z - z) * (a[i].z - z)));
}
return ret;
}
void slove()
{
double T = 10, r = 0.995; //初始温度、降温
ans = dis(X, Y, Z);
while(T > 1e-10)
{
double x = X + (rand() * 2 - RAND_MAX) * T;
double y = Y + (rand() * 2 - RAND_MAX) * T;
double z = Z + (rand() * 2 - RAND_MAX) * T;
double res = dis(x, y, z);
if(res < ans) //条件满足更新最优解
{
ans = res;
X = x, Y = y, Z = z;
}
else if(exp((ans - res) / T) * RAND_MAX > rand()) //不满足则随机更新,跳出局部最优解
{
X = x, Y = y, Z = z;
}
T *= r; //降温
}
}
int main()
{
srand(time(NULL));
scanf("%d", &n);
for(int i = 0; i < n; ++i)
{
scanf("%lf%lf%lf", &a[i].x, &a[i].y, &a[i].z);
X += a[i].x, Y += a[i].y, Z += a[i].z;
}
X /= n, Y /= n, Z /= n;
slove();
printf("%.10f\n", ans);
return 0;
}