洛谷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 }

猜你喜欢

转载自www.cnblogs.com/linxif2008/p/9726736.html
今日推荐