啓蒙博客:https://blog.csdn.net/AI_BigData_wh/article/details/77943787?locationNum=2&fps=1
POJ2069:最小球覆蓋
被精度搞死。。POJ做題經常被精度卡到懷疑人生。。好感-1-1-1...-1
隊友的模擬退火的模版好像是錯的(但是能過HDU3007,很玄學了)。初識溫度的設置不能太大,會影響最終結果的準確度。
ac代碼:
#include <iostream>
#include <cmath>
using namespace std;
const int maxn = 40;
const double eps = 1e-7;
const double DINF = 0x7fffffff;
const double initT = 400;//設小了可能會wa,POJ2069開到500會wa,200-400可行
struct Point{
double x, y, z;
Point(double x = 0, double y = 0, double z = 0):x(x),y(y),z(z){}
};
Point p[maxn];
int n;
double dist(Point a, Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));
}
double sa()
{
double ans = DINF, T = initT;//T相當與迭代次數,多次結果更準確
Point ansp = Point(0,0,0);// ansp記錄最小球的圓心
while(T > eps)
{
double maxd = -1;
int k = 0;
for(int i = 0; i < n; i++)
if(dist(ansp, p[i]) > maxd)
{
maxd = dist(ansp, p[i]);
k = i;//不單獨開一個點maxd記錄和當前圓心距離最遠的點,會wa,精度問題吧
}
ans = min(ans, maxd);//更新最小半徑
ansp.x += (p[k].x-ansp.x)*T/maxd;
ansp.y += (p[k].y-ansp.y)*T/maxd;
ansp.z += (p[k].z-ansp.z)*T/maxd;
T *= 0.98;//降溫
}
return ans;
}
int main()
{
//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
while(scanf("%d", &n))
{
if(n == 0) break;
for(int i = 0; i < n; i++) scanf("%lf %lf %lf", &p[i].x, &p[i].y, &p[i].z);
printf("%.5lf\n", sa());
}
return 0;
}
HDU3007: 最小圓覆蓋
數據比較水吧。用隊友的模版也能過,兩個都貼上吧。!(◎_◎;)
mine:
#include <iostream>
#include <cmath>
using namespace std;
const int maxn = 550;
const double eps = 1e-7;
const double DINF = 0x7fffffff;
const double initT = 400;//設小了可能會wa,POJ2069開到500會wa
struct Point{
double x, y;
Point(double x = 0, double y = 0):x(x),y(y){}
};
Point p[maxn];
int n;
double dist(Point a, Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double sa()
{
double ans = DINF, T = initT;//T相當與迭代次數,多次結果更準確
Point ansp = Point(0,0);//ansp記錄最小球的圓心
while(T > eps)
{
double maxd = -1;
int k = 0;
for(int i = 0; i < n; i++)
if(dist(ansp, p[i]) > maxd)
{
maxd = dist(ansp, p[i]);
k = i;
}
ans = min(ans, maxd);//更新最小半徑
ansp.x += (p[k].x-ansp.x)*T/maxd;
ansp.y += (p[k].y-ansp.y)*T/maxd;
T *= 0.98;//降溫
}
printf("%.2lf %.2lf %.2lf\n", ansp.x, ansp.y, ans);
}
int main()
{
//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
while(scanf("%d", &n))
{
if(n == 0) break;
for(int i = 0; i < n; i++) scanf("%lf %lf", &p[i].x, &p[i].y);
sa();
}
return 0;
}
WJX‘s:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int INF=0x3f3f3f3f;
const int maxn=550;
const double eps=1e-3; //精度
const double start_T=1000; //初始溫度
const double rate=0.98; //溫度下降速率
struct point
{
double x;
double y;
} p[maxn];
int N;
double dist(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double solve()
{
double T=start_T;
point ans_p={0,0}; //初始點
double ans=1e99; //預設一個較大值
while(T>eps)
{
point maxd_p=p[1];
for(int i=2;i<=N;i++)
{
if(dist(ans_p,p[i])>dist(ans_p,maxd_p))
maxd_p=p[i];
}
//找到距離ans_p最遠的點,maxd_p
ans=min(ans,dist(ans_p,maxd_p));
ans_p.x+=(maxd_p.x-ans_p.x)*(T/start_T); //以一定概率靠近maxd_p
ans_p.y+=(maxd_p.y-ans_p.y)*(T/start_T);
T*=rate;
}
printf("%.2lf %.2lf %.2lf\n", ans_p.x, ans_p.y, ans);
}
int main()
{
//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);
while(scanf("%d",&N) && N)
{
for (int i = 1; i <= N; i++)
scanf("%lf %lf", &p[i].x, &p[i].y);
solve();
}
return 0;
}