洛谷P1337 [JSOI2004]平衡点 / 吊打XXX
洛谷P1337 [JSOI2004]平衡点 / 吊打XXX
题意:
有n个重物,每个重物系在一条足够长的绳子上。每条绳子自上而下穿过桌面上的洞,然后系在一起。图中X处就是公共的绳结。假设绳子是完全弹性的(不会造成能量损失),桌子足够高(因而重物不会垂到地上),且忽略所有的摩擦。
问绳结X最终平衡于何处。
思路:
模拟退火。。。
以所有坐标的平均点为绳结坐标的搜索初始点
然后随机两个数dx,dy来产生新的搜索坐标
然后就是照着模拟退火的套路来
代码:
因为是模拟退火的随机算法,所以一次提交不一定能过。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <algorithm> 6 #include <ctime> 7 using namespace std; 8 #define MAXN 1010 9 #define T0 2000 10 #define TK 1e-15 11 #define DT 0.998 12 struct Node{ 13 int x,y,w; 14 Node(){} 15 Node(int x,int y,int w):x(x),y(y),w(w){} 16 }p[MAXN]; 17 int i,j,k,m,n,x,y,w; 18 double ansx,ansy; 19 double count(double x,double y){ 20 double tx,ty,ans=0; 21 for(register int i=1;i<=n;i++){ 22 tx=x-p[i].x,ty=y-p[i].y; 23 ans+=sqrt(tx*tx+ty*ty)*p[i].w; 24 } 25 return ans; 26 } 27 void simulate_anneal(){ 28 double tx=ansx,ty=ansy,t=T0,delta; 29 double cur=count(tx,ty),tmp; 30 while(t>TK){ 31 tx=ansx+((rand()<<1)-RAND_MAX)*t; 32 ty=ansy+((rand()<<1)-RAND_MAX)*t; 33 tmp=count(tx,ty); 34 delta=tmp-cur; 35 if(delta<0){ 36 ansx=tx,ansy=ty; 37 cur=tmp; 38 }else{ 39 if(exp(-delta/t)*RAND_MAX>rand()) ansx=tx,ansy=ty; 40 } 41 t*=DT; 42 } 43 } 44 int main(){ 45 scanf("%d",&n); 46 ansx=ansy=0; 47 for(i=1;i<=n;i++){ 48 scanf("%d%d%d",&x,&y,&w); 49 p[i]=Node(x,y,w); 50 ansx+=x,ansy+=y; 51 } 52 ansx/=1.0*n; ansy/=1.0*n; 53 srand((unsigned int)time(NULL)); 54 simulate_anneal(); 55 simulate_anneal(); 56 simulate_anneal(); 57 printf("%.3lf %.3lf\n",ansx,ansy); 58 return 0; 59 }