题意:
一些带重力的点用一个节点连接,问最后节点的位置。也就是求重心。
分析:
由于搜寻空间较大,所以采用随机算法进行计算。
模拟退火:是一种通用概率算法,用来在一个大的搜寻空间中寻找明题的最优解。
爬山算法:局部择优的方法,采用启发式方法,是对深度优先搜索的一种改进,利用反馈信息帮助生成解的决策。
其实模拟退火是爬山算法的增强版,爬山只能找到局部最优解,而模拟退火能找到全局最优解。但是爬山算法的效率就显得高出模拟退火很多了。在不存在局部最优解的时候爬山算法往往是更优的选择。
推荐博文:http://www.cnblogs.com/GuoJiaSheng/p/4192301.html
/*
爬山算法实现
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
struct node{
double x,y,z;
}a[maxn],ans,now;
double Min=1e17;
int n;
inline double dist(node a,node b){
return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
}
inline bool judge(node p){
double res=0;
for(int i=1;i<=n;i++){
res+=dist(p,a[i])*a[i].z;
}
if(res<Min){
Min=res;
ans=p;
return true;
}
return false;
}
inline double get_rand(){
return rand()%1000/1000.0;
}
inline void hillclimb(double T){
node tmp;
while(T>0.001){
tmp.x=now.x+T*(get_rand()*2-1);
tmp.y=now.y+T*(get_rand()*2-1);
if(judge(tmp)){
now=tmp;
}
T*=0.993;
}
}
int main(){
srand(time(NULL));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z);
now.x+=a[i].x,now.y+=a[i].y;
}
now.x/=n;now.y/=n;
hillclimb(100000);
printf("%.3f %.3f\n",ans.x,ans.y);
return 0;
}
/*
模拟退火实现
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
struct node{
double x,y,z;
}a[maxn],ans,now;
double Min=1e17;
int n;
inline double dist(node a,node b){
return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));
}
inline double judge(node p){
double res=0;
for(int i=1;i<=n;i++){
res+=dist(p,a[i])*a[i].z;
}
if(res<Min){
Min=res;
ans=p;
}
return res;
}
inline double get_rand(){
return rand()%1000/1000.0;
}
inline void SA(double T){
node tmp;
while(T>0.001){
tmp.x=now.x+T*(get_rand()*2-1);
tmp.y=now.y+T*(get_rand()*2-1);
double f=judge(now)-judge(tmp);
if(f>0||exp(f/T)>get_rand()){
now=tmp;
}
T*=0.993;
}
for(int i=1;i<=1000;i++){
tmp.x=ans.x+T*(get_rand()*2-1);
tmp.y=ans.y+T*(get_rand()*2-1);
judge(tmp);
}
}
int main(){
srand(time(NULL));
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lf%lf%lf",&a[i].x,&a[i].y,&a[i].z);
now.x+=a[i].x,now.y+=a[i].y;
}
now.x/=n;now.y/=n;
SA(100000);
printf("%.3f %.3f\n",ans.x,ans.y);
return 0;
}