POJ 2420 A Star not a Tree?【爬山法】
題目大意:在二維平面上找出一個點,使它到所有給定點的距離和最小,距離定義為歐氏距離,求這個最小的距離和是多少(結果需要四舍五入)?
思路:如果不能加點,問所有點距離和的最小值那就是經典的MST,如果只可以加一個點問最小值就是廣義的費馬點的問題,如果加點的數目不加限制,那問題就成了斯坦納樹的問題(介個屬于NPC問題)
這題顯然就是廣義費馬點問題,可以采用局部貪心法,從一個初始點出發,不斷向上下左右四個方向拓展,如果在一個方向上走過去到所有點的距離和小于目前這個點到所有點的距離和,那就更新目前點的值,直到從四個方向拓展都不能比目前的點更優,那就說明目前的點屬于局部最優,那就減少步長,從剛才給出點處繼續搜索,直到精度小于題目所需的精度(整數)
需要注意的是局部貪心(又叫爬山法)很容易卡在局部最優上,因此往往隨機初始點多次,以保證局部最優是全局最優,但廣義費馬點好像這種局部最優的點不多的樣子,選原點為初始點就可以AC這題
//POJ2420
#include <cstdio>
#include <iostream>
#include <string.h>
#include <math.h>
#define maxn 110
const short dx[5]={0,1,-1,0,0},dy[5]={0,0,0,1,-1};
using namespace std;
double x[maxn]={0},y[maxn]={0};int n;
double sumlen(double xx,double yy)
{
???double ret=0;
???for(int i=1;i<=n;i++)
??? {
???????ret+=sqrt((xx-x[i])*(xx-x[i])+(yy-y[i])*(yy-y[i]));
??? }
???return ret;
}
int main()
{
???scanf("%d",&n);
???for(int i=1;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]);
???double a=0,b=0,min=sumlen(a,b),step=100;
???while (step>0.1)
??? {
???????short flag=1;
???????while (flag==1)//如果這層循環結束,說明從四個方向拓展都不能得到更優解也就是達到了局部最優解
???????{
???????????flag=0;
???????????for(int i=1;i<=4;i++)
???????????{
??????????????? doublexx=a+dx[i]*step,yy=b+dy[i]*step,t=sumlen(xx,yy);
??????????????? if (t<min){min=t;a=xx;b=yy;flag=1;}
???????????}
???????}
???????step/=2;
??? }
???printf("%d",(int)(min+0.5));
???return 0;
}
轉載于:https://www.cnblogs.com/philippica/p/4006985.html
總結
以上是生活随笔為你收集整理的POJ 2420 A Star not a Tree?【爬山法】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (王道408考研操作系统)第五章输入/输
- 下一篇: java多线程之消费者生产者模式