luogu1337JSOI2004平衡点 / 吊打XXX(模拟退火)
Posted 小哈里
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu1337JSOI2004平衡点 / 吊打XXX(模拟退火)相关的知识,希望对你有一定的参考价值。
problem
solution
题意:
- 给出n个重物的坐标和重量,他们通过一根绳子穿过正上方的洞连在桌面上的某个绳结处,求该绳结的坐标位置。
思路:
- 根据物理知识:当系统处于平衡状态时,系统的总能量最小。此时系统的总能量是等于各个物体的重力势能,在质量一定时,即要求物体离地最近,离桌子最远。那么,也就是绳子在桌子上的距离尽量的小。
- 模拟退火,每次随机一个桌子上的点,判断n个洞口到他的总距离和是大了还是小了,找最小的即可。其实就是之前写过的“星星还是树”,就是空间n个点,找距离和最近的点即可。
#include<bits/stdc++.h>
using namespace std;
int n;
struct node{int x, y, w;}a[2020];
struct node2{double x, y, w;}ans;
double calc(double x, double y){//计算系统总能量
double res = 0;
for(int i = 1; i <= n; i++){
double dx=x-a[i].x, dy=y-a[i].y;
res += sqrt(dx*dx+dy*dy)*a[i].w;
}
return res;
}
void sa(){
for(double t=3000; t >= 1e-15; t*=0.996){
node2 tmp;
tmp.x = ans.x+(rand()*2-RAND_MAX)*t;
tmp.y = ans.y+(rand()*2-RAND_MAX)*t;
tmp.w = calc(tmp.x, tmp.y);
double dt =tmp.w-ans.w;
if(dt<0)ans = tmp;
else if(exp(-dt/t)>(double)rand()/RAND_MAX)ans=tmp;
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>n;
for(int i = 1; i <= n; i++){
cin>>a[i].x>>a[i].y>>a[i].w;
ans.x+=a[i].x, ans.y+=a[i].y;
}
ans.x /= n, ans.y /= n, ans.w = calc(ans.x,ans.y);
sa();
cout<<fixed<<setprecision(3)<<ans.x<<" "<<ans.y<<"\\n";
return 0;
}
以上是关于luogu1337JSOI2004平衡点 / 吊打XXX(模拟退火)的主要内容,如果未能解决你的问题,请参考以下文章