poj 2420 求n个点的费马点 随机算法解决
来源:互联网 发布:公司网络改造方案 编辑:程序博客网 时间:2024/05/22 07:58
还是跟那题poj 1379 run away一样的做法
http://www.cnblogs.com/wuyiqi/archive/2011/12/08/2280885.html
改一下最优的方法(到n个点的距离之和)就好了
View Code
//求n边形的费马点
//即找到一个点使得这个点到n个点的距离之和最小
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
const double inf = 1e10;
const double pi = acos(-1.0);
const int Rp = 4;//初始时随机选择一些点,不用太多
const int shift = 60;//但是方向一定要多
struct point {
double x,y;
void goto_rand_dir(double key)
{
double d=2*pi*(double)rand()/RAND_MAX;
x+=key*sin(d);
y+=key*cos(d);
}
void Get_Rand_Point(int a,int b)
{
x=rand()%a+1;
y=rand()%b+1;
}
}p[1010],randp[Rp];
double Dis(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
double dis[Rp];
int main()
{
int i,j,x,y,k,m;
srand(time(NULL));
while(scanf("%d",&m)!=EOF)
{
for(i=0;i<m;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
x=10000;y=10000;
double tmp;
for(i=0;i<Rp;i++)
{
dis[i]=inf;
randp[i].Get_Rand_Point(x,y);
tmp=0;
for(j=0;j<m;j++)
{
tmp+=Dis(randp[i],p[j]);
}
if(tmp<dis[i])
dis[i]=tmp;
}
double key=sqrt(1.0*(x*x+y*y));//初始的步长,要保证初始点从该点出发肯定能包括整个区域
while(key>=0.01)
{
for(i=0;i<Rp;i++)
{
for(j=0;j<shift;j++)
{
point cc=randp[i];
cc.goto_rand_dir(key);
if(cc.x<0||cc.y<0||cc.x>x||cc.y>y) continue;
tmp=0;
for(k=0;k<m;k++)
{
tmp+=Dis(cc,p[k]);
}
if(tmp<dis[i]) //如果从i点出发随机移动的点比原来的点更优,则接受该移动
{
dis[i]=tmp;
randp[i]=cc;
}
}
}
key=key*0.6;//可灵活调整
}
for(i=k=0;i<Rp;i++)
if(dis[i]<dis[k])
k=i;
printf("%.0lf\n",dis[k]);
}
return 0;
}
网上的另一种做法,一个点朝四个方向按一定方向搜索,然后再逐步缩小步长
参考自http://hi.baidu.com/perfectcai_/blog/item/65349a48840bc4e382025cc2.html
代码写的简单多了,但这种做法有时候会错。。因为只有四个方向,还是上面的做法保险
也贴贴代码吧
View Code
#include <iostream>
#include <cmath>
#define N 128
#define EPS 0.1
using namespace std;
int n;
double x[N], y[N];
double f(double a, double b)
{
int i;
double ans = 0;
for (i=0; i<n; i++)
ans += sqrt((a-x[i])*(a-x[i]) + (b-y[i])*(b-y[i]));
return ans;
}
int main()
{
double ans, step, temp, a, b, ta, tb;
int i;
bool flag;
while (scanf("%d", &n) == 1)
{
for (i=0; i<n; i++)
scanf("%lf%lf", &x[i], &y[i]);
a = x[0];
b = y[0];
ans = f(a, b);
step = 100;
while (step > EPS)
{
flag = 1;
while (flag)
{
flag = 0;
temp = f(a+step, b);
if (temp < ans)
{
flag = 1;
ans = temp;
ta = a + step;
tb = b;
}
temp = f(a-step, b);
if (temp < ans)
{
flag = 1;
ans = temp;
ta = a - step;
tb = b;
}
temp = f(a, b+step);
if (temp < ans)
{
flag = 1;
ans = temp;
ta = a;
tb = b + step;
}
temp = f(a, b-step);
if (temp < ans)
{
flag = 1;
ans = temp;
ta = a;
tb = b - step;
}
a = ta;
b = tb;
}
step /= 2;
}
printf("%.0lf\n", ans);
}
return 0;
}
- poj 2420 求n个点的费马点 随机算法解决
- 算法导论求n个点的最小距离
- 求n个点的费马点的花式乱搞
- [算法] 已知在平面坐标系内有N个点,求离开给定坐标距离最近的10个点
- (Relax ST1.13)POJ 2780 Linearity(给出若干个点,求最多有多少个点共线,不能使用n^3算法)
- 随机在圆上生成n个点,这n个点在同一半圆的概率是多少?
- 如何设计一个高效算法从N个正整数中,随机选取n个不同的随机数 n<=N
- (阶段四1.3)UVA 11300 Spreading the Wealth(利用中位数来解决求某一个点到给定的n个点的距离的最小值)
- Graham 扫描算法求凸包,poj 2187(水题但是是我的第一个求n点集凸包模板)
- 求第n个奇素数的递归算法
- 每日一道算法题:求N个整数的最大公约数
- 算法题:求前n个质数的和
- 欧几里得算法求n个数据的最大公约数
- Java算法----递归求N个正数的最小公倍数
- 【质数算法】——判断质数、求小于N的质数、求前N个质数
- 【算法】给定正数N,求N的阶乘N!的末位有多少个0
- 数轴上从左到右有n个点a[0],a[1]…,a[n-1],给定一根长度为L的绳子,求绳子最多能覆盖其中的几个点。要求算法复杂度为o(n)。
- 数轴上从左到右有n个点a[0],a[1]…,a[n-1],给定一根长度为L的绳子,求绳子最多能覆盖其中的几个点。要求算法复杂度为o(n)。
- c++入门
- c
- poj 1201 intervals 我的第一个差分约束
- hdu 3932 最小覆盖圆 随机算法做法
- 一个最小 一个最大 poj 1379 hdu 3932
- poj 2420 求n个点的费马点 随机算法解决
- hdu 1007 求最近点对
- poj 1275 差分约束
- poj 3159 差分约束 用栈代替队列
- dijkstra + heap
- hdu 3440 差分约束
- hdu 1011 树形DP
- 金明的预算方案 有依赖的背包
- hdu 3792 树状数组