您的位置:首页 > 其它

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

2014-11-14 21:03 381 查看
题意:

平面上给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;	
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: