hdu 3932Groundhog Build Home 【爬山演算法】
阿新 • • 發佈:2018-11-04
題意:求到n個點的最大距離最小化的點
///爬山演算法 //是個單峰函式,還有那個bzoj3680 #include<bits/stdc++.h> #define mp make_pair #define sz(x) int((x).size()) #define fin freopen("in.txt","r",stdin) #define fout freopen("out.txt","w",stdout) #define io ios::sync_with_stdio(0),cin.tie(0) using namespace std; typedef long long ll; typedef pair<int,int> PII; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; const int maxn = 1e4 + 5; int n; double X,Y; // struct point { double x,y; } p[maxn],pp; double ans=1e10; double dis(point a,point b) { return ((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int get(point x) { double res=-1; int k; for(int i=1; i<=n; ++i) { double m=dis(p[i],x); if(m>res) res=m,k=i; } ans=min(ans,dis(x,p[k])); return k; } void hc() { double T=1.0,eps=1e-8; while(T>eps) { //if(pp.x<=X&&pp.y<=Y&&pp.x>=0&&pp.y>=0) // { int k=get(pp); pp.x=pp.x+(p[k].x-pp.x)*T; pp.y=pp.y+(p[k].y-pp.y)*T; // } T*=0.999; } } int main() { double X,Y; while(cin>>X>>Y>>n) { for(int i=1; i<=n; ++i) cin>>p[i].x>>p[i].y; pp.x=X/2.0,pp.y=Y/2.0; ans=1e10; hc(); printf("(%.1f,%.1f).\n",pp.x,pp.y); printf("%.1f\n",sqrt(ans)); } }
/退火演算法 退火了一下午還是wa
#include<bits/stdc++.h> #define mp make_pair #define sz(x) int((x).size()) #define fin freopen("in.txt","r",stdin) #define fout freopen("out.txt","w",stdout) #define io ios::sync_with_stdio(0),cin.tie(0) using namespace std; typedef long long ll; typedef pair<int,int> PII; const int inf = 0x3f3f3f3f; const int mod = 1e9 + 7; const int maxn = 1e4 + 5; int n;double X,Y; struct point { double x=0,y=0; } p[maxn],now,nex,ansp; 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 f(point x) { //評估函式 double res = -1.0; for (int i=1;i<=n;i++) res=max(res,dis(x,p[i])); return res; } double ans; void sa() { ans=1e111;//最開始的能量值,初始很大就可以,不用修改 double T=1e8; //初始溫度, (可以適當修改,最好和給的資料最大範圍相同,或者縮小其原來0.1) double d=0.9998; //降溫係數 (可以適當修改,影響結果的精度和迴圈的次數,) double eps=1e-4; //最終溫度 (要是因為精度問題,可以適當減小最終溫度) double TT=1; //採納新解的初始概率 double dd=0.99; //(可以適當修改,採納新解變更的概率)(這個概率下面新解更新的時候,最好和未採納的新解更新的次數是一半一半) double res=f(now); //傳入的初始預設解(now)下得到的評估能量值 if (res<ans) ans=res,ansp=now;//ansp終解 int num=0; while (T>eps) { for (double i=-1;i<=1;++i) for (double j=-1;j<=1;++j) if ((now.x+T*i>=eps)&&(now.x+T*i<=X)&&(now.y+T*j<=Y)&&(now.y+T*j>=eps)) { nex.x=now.x+T*i,nex.y=now.y+T*j;//新解 double tmp=f(nex);//新解下的評估能量值 if (tmp<ans) ans=tmp,ansp=nex;//降溫成功,更新當前最優解 if (tmp<res) res=tmp,now=nex;// 降溫成功,採納新解 else if (TT>rand()%10000/10000.0) res=tmp,now=nex,cout<<"======"<<endl;//沒有 降溫成功,但是以一定的概率採納新解 else cout<<"="<<endl;//用於測試,設定的採納新解的概率,是否為一半一半,可以適當修改降溫引數dd } T*=d; TT*=dd; num++; }//cout<<num<<endl; } int main() { srand(time(0)); while(cin>>X>>Y>>n) { // cin>>X>>Y>>n; now.x=now.y=0; for (int i=1;i<=n;++i) { cin>>p[i].x>>p[i].y;//scanf("%f%f",&p[i].x,&p[i].y); now.x+=p[i].x,now.y+=p[i].y; }//cout<<now.x<<' '<<now.y<<endl; now.x/=n,now.y/=n; sa(); printf("(%.2f,%.2f).\n",ansp.x,ansp.y); printf("%.2f\n",ans); } return 0; }