洛谷 P1337 [JSOI2004]平衡點 / 吊打XXX(模擬退火)
阿新 • • 發佈:2021-07-17
傳送門
解題思路
特別狗的一道題
根據重力勢能最小時平衡(??),可以進行模擬退火。
其他的套板子行了。
然後我就寫掛了(交了24次)
AC程式碼
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #include<algorithm> #include<ctime> #include<iomanip> using namespace std; const int maxn=1005; const double delta=0.996; int n; double ans,ansx,ansy,sumx,sumy; struct node{ double x,y,w; }a[maxn]; double cal(double x,double y){ double ans=0; for(int i=1;i<=n;i++){ double d=(x-a[i].x)*(x-a[i].x)+(y-a[i].y)*(y-a[i].y); d=sqrt(d); ans+=d*a[i].w; } return ans; } void SA(){ double t=3000,x=ansx,y=ansy; while(t>1e-15){ double newx=x+(rand()*2-RAND_MAX)*t,newy=y+(rand()*2-RAND_MAX)*t; double res=cal(newx,newy); double cha=res-ans; if(cha<0) ans=res,ansx=x=newx,ansy=y=newy; else if(exp(-cha/t)*RAND_MAX>rand()) x=newx,y=newy; t*=delta; } } int main(){ ios::sync_with_stdio(false); srand(time(NULL)); cin>>n; for(int i=1;i<=n;i++){ cin>>a[i].x>>a[i].y>>a[i].w; sumx+=a[i].x; sumy+=a[i].y; } ansx=sumx/n; ansy=sumy/n; ans=1e18; while((double)clock()/CLOCKS_PER_SEC<=0.85) SA(); cout<<fixed<<setprecision(3)<<ansx<<" "<<ansy; return 0; }