首页 > Web开发 > 详细

P1337 [JSOI2004]平衡点 / 吊打XXX

时间:2019-08-12 20:20:25      阅读:117      评论:0      收藏:0      [点我收藏+]

[JSOI2004]平衡点 / 吊打XXX

题目描述

如图:有n个重物,每个重物系在一条足够长的绳子上。每条绳子自上而下穿过桌面上的洞,然后系在一起。图中X处就是公共的绳结。假设绳子是完全弹性的(不会造成能量损失),桌子足够高(因而重物不会垂到地上),且忽略所有的摩擦。 问绳结X最终平衡于何处。 注意:桌面上的洞都比绳结X小得多,所以即使某个重物特别重,绳结X也不可能穿过桌面上的洞掉下来,最多是卡在某个洞口处。 ![](https://cdn.luogu.org/upload/pic/148.png)

输入输出格式

输入格式

 

文件的第一行为一个正整数n(1≤n≤1000),表示重物和洞的数目。接下来的n行,每行是3个整数:Xi.Yi.Wi,分别表示第i个洞的坐标以及第 i个重物的重量。(-10000≤x,y≤10000, 0<w≤1000 )

输出格式

 

你的程序必须输出两个浮点数(保留小数点后三位),分别表示处于最终平衡状态时绳结X的横坐标和纵坐标。两个数以一个空格隔开。

输入输出样例

输入样例 #1

3
0 0 1
0 2 1
1 1 1

输出样例 #1

0.577 1.000

说明

[JSOI]
 
[思路]  模拟退火

一、模拟退火步骤

选定一个初始状态(比如选定所有点坐标的平均数),选定一个初始温度T。

当温度大于一个边界值时:

{
  随机变化坐标,变化幅度为 T 。

  计算新解与当前解的差 DE。

  如果新解比当前解优(DE > 0),就用新解替换当前解。

  否则以 exp(DE / T) 的概率用新解替换当前解。

  温度乘上一个小于1的系数,即降温。
}

这样,随着温度不断降低,变化幅度也越来越小,接受一个更劣的解的概率也越来越小。

二、模拟退火注意事项

  1. 温度T的初始值设置问题。 初始温度高,则搜索到全局最优解的可能性大,但因此要花费大量的计算时间;反之,则可节约计算时间,但全局搜索性能可能受到影响。

  2. 退火速度问题。 模拟退火算法的全局搜索性能也与退火速度密切相关。同一温度下的“充分”搜索(退火)是相当必要的,但这需要计算时间。

  3. 温度管理问题 降温系数应为正的略小于1.00的常数。

关于这道题,一切自然变化进行的方向都是使能量降低,因为能量较低的状态比较稳定。

因为物重一定,绳子越短,重物越低,势能越小,势能又与物重成正比,所以,只要使得$\sum_{i=1}^ndist[i]*weight[i]$也就是总的重力势能最小,就可以使系统平衡

 
[代码]
 
#include<cmath>
#include<ctime>
#include<cstdio>
#include<algorithm>
#define pf(x) ((x)*(x))
using namespace std;
const int N=1005;
int n;struct node{double x,y,z;}a[N];double ansx,ansy,answ=1e9;
inline double energy(double nx,double ny){
    double res=0;
    for(int i=1;i<=n;i++) res+=sqrt(pf(nx-a[i].x)+pf(ny-a[i].y))*a[i].z;
    return res;
}
inline void SA(){
    for(double T=1e5;T>=1e-14;T*=0.977){
        double tx=ansx+(rand()*2-RAND_MAX)*T;
        double ty=ansy+(rand()*2-RAND_MAX)*T;
        double tw=energy(tx,ty);
        if(tw<answ){
            ansx=tx;
            ansy=ty;
            answ=tw;
        }
        else if(exp(-(tw-answ)/T)*RAND_MAX>rand()){
            ansx=tx;
            ansy=ty;
        }
    }
}
int main(){
    srand(time(0)),srand(rand()+2000329);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z),ansx+=a[i].x,ansy+=a[i].y;
    answ=energy(ansx/=1.0*n,ansy/=1.0*n);
    while((clock()/(1.0*CLOCKS_PER_SEC))<=0.977) SA();
    printf("%.3lf %.3lf\n",ansx,ansy);
    return 0;
}

 

P1337 [JSOI2004]平衡点 / 吊打XXX

原文:https://www.cnblogs.com/shenben/p/11342217.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!