当前位置: 代码迷 >> 综合 >> poj 2420 A Star not a Tree? 随机化变步长贪心
  详细解决方案

poj 2420 A Star not a Tree? 随机化变步长贪心

热度:93   发布时间:2024-01-19 06:28:34.0

题意:

平面上给n个点,求一个点到所有点的距离之和最小。

思路:

随机化变步长贪心,与退火算法的区别是没有以一定的概率接受估值较差的点,因为起始点较多而且在每点都向较多方向更新,所以没必要用退火算法,直接变步长贪心就行,起始这么多点每次更新这么多次撞到一个全局最优点是概率很大的。一般的贪心常常会陷于局部最优,随机化利用多次不同位置的贪心搜索找出全局最优。

代码:

//poj 2420
//sepNINE
#include <iostream>
#include <cmath>
using namespace std;
const int maxN=128;
const int NUM=20;
const int PRECISION=1000;
const int TIM=30;
const double MIN=0.1;
const double alpha=0.8;
int n;struct Point
{double x,y,v;Point(){}Point(double x,double y):x(x),y(y){}	
}pnt[maxN],randPnt[NUM];double getDouble(){return (rand()%(PRECISION+1))*1.0/PRECISION;
}double getSum(Point p)
{double sum=0;for(int i=0;i<n;++i)sum+=sqrt((p.x-pnt[i].x)*(p.x-pnt[i].x)+(p.y-pnt[i].y)*(p.y-pnt[i].y));return sum;
}Point getRandPnt(Point a,Point b)
{Point p(a.x+(b.x-a.x)*getDouble(),a.y+(b.y-a.y)*getDouble());p.v=getSum(p);return p;
}  void search(double maxL)
{for(double L=maxL;L>=MIN;L=L*alpha)for(int i=0;i<NUM;++i)for(int j=0;j<TIM;++j){Point tmp=getRandPnt(Point(randPnt[i].x-L,randPnt[i].y-L),Point(randPnt[i].x+L,randPnt[i].y+L));if(tmp.v<randPnt[i].v)randPnt[i]=tmp;}		
}int main()
{int i;scanf("%d",&n);Point a(10000,10000),b(0,0);for(i=0;i<n;++i){scanf("%lf%lf",&pnt[i].x,&pnt[i].y);a.x=min(a.x,pnt[i].x);a.y=min(a.y,pnt[i].y);b.x=max(b.x,pnt[i].x);b.y=max(b.y,pnt[i].y);}for(i=0;i<NUM;++i)randPnt[i]=getRandPnt(a,b);search(max(b.x-a.x,b.y-a.y));double ans=randPnt[0].v;for(i=0;i<NUM;++i)ans=min(ans,randPnt[i].v);printf("%.0lf",ans);return 0;	
} 


  相关解决方案