HDU 3007 Buried memory(點集最小圓覆蓋 模擬退火解法)
阿新 • • 發佈:2018-12-24
這題和ZOJ1450是一樣的,不過這個題目我換個解法
ZOJ1450我是用標準求最小點集覆蓋求圓的方法來做的,速度很快
對於這一題目,我用的是模擬退火思想,每次像正確結果逼近
不過精度一點也不好控制,還有step也一點也不好控制,這些值都不能隨便
取,要取特定意義的值才行!
噁心的是在ZOJ上就過不了!
#include <string.h> #include <stdio.h> #include <algorithm> #include <cmath> #include <iostream> using namespace std; #define maxn 1500 #define MAX(a,b) (a>b?a:b) #define eps 1e-20 struct point{ double x,y; }po[maxn],cir; int n; double step; double dis(point &a,point &b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } double find_max(point &a){ double ans=0,t; for(int i=0;i<n;i++){ t=dis(po[i],a); ans=MAX(ans,t); } return ans; } int solve(){ int i,j,k; point temp,re; double p,now; step=find_max(po[0]); cir=po[0]; while(step>eps){ temp=cir; temp.x+=step; re=temp; now=find_max(temp); temp=cir; temp.y+=step; p=find_max(temp); if(p < now) now=p,re=temp; temp=cir; temp.y-=step; p=find_max(temp); if(p < now) now=p,re=temp; temp=cir; temp.x-=step; p=find_max(temp); if(p < now) now=p,re=temp; step/=2; cir=re; } printf("%.2lf %.2lf %.2lf\n",cir.x,cir.y,find_max(cir)); return 0; } int main(){ int i,j,k; while(scanf("%d",&n),n){ for(i=0;i<n;i++) scanf("%lf%lf",&po[i].x,&po[i].y); if(n==1){ printf("%.2lf %.2lf %.2lf\n",po[0].x,po[0].y,0.0); continue; } if(n==2){ printf("%.2lf %.2lf %.2lf\n",(po[0].x+po[1].x)/2,(po[0].y+po[1].y)/2,dis(po[0],po[1])/2); continue; } solve(); } return 0; }