BZOJ 3680 吊打XXX
模拟退火。
退完火之后还要随机调整位置。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<map> #include<set> #include<queue> #include<stack> #include<ctime> #include<iostream> using namespace std; typedef long long LL; const double pi=acos(-1.0); void File() { freopen("D:\\in.txt","r",stdin); freopen("D:\\out.txt","w",stdout); } template <class T> inline void read(T &x) { char c = getchar(); x = 0; while(!isdigit(c)) c = getchar(); while(isdigit(c)) { x = x * 10 + c - '0'; c = getchar(); } } double T; int n; struct Point { double x,y,w; }p[10010]; Point ans; double Rand() { return 1.0*(rand()%1000+1)/1000; } 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 get(Point t) { double c=0; for(int i=1;i<=n;i++) c+=dis(t,p[i])*p[i].w; return c; } int main() { srand(19951129); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].w); ans.x=0; ans.y=0; for(int i=1;i<=n;i++) ans.x+=p[i].x; for(int i=1;i<=n;i++) ans.y+=p[i].y; ans.x/=n; ans.y/=n; T=1000000; while(T>0.001) { Point nx; nx.x=ans.x+T*(Rand()*2-1); nx.y=ans.y+T*(Rand()*2-1); double A=get(ans),B=get(nx); if(A-B>=0||exp((A-B)/T)>Rand()) ans=nx; T=T*0.99; } for(int i=1;i<=1000;i++) { Point nx; nx.x=ans.x+T*(Rand()*2-1); nx.y=ans.y+T*(Rand()*2-1); double A=get(ans),B=get(nx); if(A-B>=0) ans=nx; } printf("%.3f %.3f\n",ans.x,ans.y); return 0; }