题目:洛谷P1337。
题目大意:
有n个重物,每个重物有一个重量w,并且绑在一条绳子上。这些绳子在桌面上打成一个结。问结在哪里才能使重物平衡。
解题思路:
题意就是要求(sumlimits_{i=1}^n d_i imes w_i)最小((d_i)为重物i到结的距离)。
模拟退火即可。
C++ Code:
#include<bits/stdc++.h> #define eps 1e-15 #define delta 0.991 struct things{ int x,y,w; }p[1005]; struct Answer{ double x,y,w; }ans,start,now; int n,xxx=0,yyy=0; inline int readint(){ int d=0,c=getchar(),f=0; for(;!isdigit(c);c=getchar())f=c=='-'; for(;isdigit(c);c=getchar())d=(d<<3)+(d<<1)+(c^'0'); return f?-d:d; } inline double calc(const double xx,const double yy){ double r=0; for(int i=1;i<=n;++i){ double x=p[i].x-xx,y=p[i].y-yy; r+=sqrt(x*x+y*y)*p[i].w; } return r; } int main(){ n=readint(); for(int i=1;i<=n;++i){ xxx+=(p[i].x=readint()),yyy+=(p[i].y=readint()); p[i].w=readint(); } ans=start=(Answer){1.*xxx/n,1.*yyy/n,calc(1.*xxx/n,1.*yyy/n)}; srand(time(0)); for(int T=20;T;--T){ now=start; for(double nT=5333;nT>eps;nT*=delta){ double nx=now.x+((rand()<<1ll)-RAND_MAX)*nT; double ny=now.y+((rand()<<1ll)-RAND_MAX)*nT; double res=calc(nx,ny); if(res<ans.w)ans=(Answer){nx,ny,res}; if(res<now.w||exp((res-now.w)/nT)*RAND_MAX<rand()) now=(Answer){nx,ny,res}; } } printf("%.3f %.3f ",ans.x,ans.y); return 0; }