BZOJ3680 & 洛谷1337:[JSOI2004]平衡点/吊打XXX——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3680
https://www.luogu.org/problemnew/show/P1337
有n个重物,每个重物系在一条足够长的绳子上。每条绳子自上而下穿过桌面上的洞,然后系在一起。图中X处就是公共的绳结。假设绳子是完全弹性的(不会造成能量损失),桌子足够高(因而重物不会垂到地上),且忽略所有的摩擦。
问绳结X最终平衡于何处。
注意:桌面上的洞都比绳结X小得多,所以即使某个重物特别重,绳结X也不可能穿过桌面上的洞掉下来,最多是卡在某个洞口处。
学一发乱搞。
当整个系统稳定的时候,其能量肯定是最小的,而能量取决于每个物品的高度*重量。
如果这个值越大则能量就越大。
当然高度=桌子高度-绳长+物品到结点距离s,前两个都是常量,于是可用s*重量来代替之,当这个值越大则能量越大。
于是拍上一个模拟退火,试图找到能量最小的点就行了。
#include<cmath> #include<queue> #include<cstdio> #include<cctype> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long double dl; const int N=1e4+5; const dl T=13570; const dl eps=1e-15; const dl delta=0.99; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } struct iron{ dl x,y,w; }a[N]; int n; dl xx,yy,t,ans=9e18; inline dl suan(dl x,dl y){ dl res=0; for(int i=1;i<=n;i++){ dl dx=x-a[i].x,dy=y-a[i].y; dl dis=sqrt(dx*dx+dy*dy); res+=dis*a[i].w; } return res; } void simulate_anneal(){ t=T; while(t>eps){ dl nx=xx+(rand()*2-RAND_MAX)*t; dl ny=yy+(rand()*2-RAND_MAX)*t; dl nans=suan(nx,ny); dl dans=nans-ans; if(dans<-eps){ xx=nx;yy=ny;ans=nans; }else if(rand()<exp(-dans/t)*RAND_MAX){ xx=nx;yy=ny; } t*=delta; } } int main(){ srand(19260817); n=read(); for(int i=1;i<=n;i++){ a[i].x=read(),a[i].y=read(),a[i].w=read(); xx+=a[i].x,yy+=a[i].y; } xx/=n,yy/=n; simulate_anneal(); printf("%.3Lf %.3Lf\n",xx,yy); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++