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/+

+++++++++++++++++++++++++++++++++++++++++++

posted @ 2018-06-01 15:40  luyouqi233  阅读(253)  评论(0编辑  收藏  举报