您的位置:首页 > 其它

POJ 1379 (随机算法)模拟退火

2015-05-26 14:05 344 查看
题目大意:

给定一堆点,找到一个点的位置使这个点到所有点中的最小距离最大

这里数据范围很小,精度要求也不高,我们这里可以利用模拟退火的方法,随机找到下一个点,如果下一个点比当前点优秀就更新当前点

参考:http://www.cnblogs.com/heaad/archive/2010/12/20/1911614.html
http://wenku.baidu.com/view/0c6b5df5f61fb7360b4c65a9.html
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <climits>
#include <cmath>
#include <queue>
#include <cstdlib>
#include <ctime>
using namespace std;
#define random(x) ((rand()%x)+1)
#define N 1005
#define ll long long
#define eps 1e-4
const double PI = acos(-1.0);
const int INF = INT_MAX;
const int P = 20;
const int L = 30;

double x,y;
int n;
double dist
;

struct Point{
double x,y;
Point(double x=0 , double y=0):x(x),y(y){}
}p
, tmp
;

double dis(Point a , Point b)
{
double x = a.x-b.x , y = a.y - b.y;
return sqrt(x*x+y*y);
}

double min_dis(Point t)
{
double minn = 1e20;
for(int i=0 ; i<n ; i++) minn=min(minn , dis(t , p[i]));
return minn;
}

bool ok(Point t)
{
return t.x>=0 && t.x<=x && t.y>=0 && t.y<=y;
}

int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in" , "r" , stdin);
#endif // ONLINE_JUDGE
srand(time(0));
int T;
scanf("%d" , &T);
while(T--)
{
Point ans;
double ret=0;

scanf("%lf%lf%d" , &x , &y , &n);
for(int i=0 ; i<n ; i++){
scanf("%lf%lf" , &p[i].x , &p[i].y);
}

for(int i=0 ; i<P ; i++){
tmp[i].x = random(1000)/1000.0*x;
tmp[i].y = random(1000)/1000.0*y;
dist[i] = min_dis(tmp[i]);
}
double step = sqrt(x*x+y*y)/2;
while(step>eps){

for(int i=0 ; i<P ; i++){
Point cur;
for(int j=0 ; j<L ; j++){
double ang = random(1000)/1000.0*2*PI;
cur.x = tmp[i].x+cos(ang)*step;
cur.y = tmp[i].y+sin(ang)*step;
if(!ok(cur)) continue;
double val = min_dis(cur);
if(val>dist[i]){
tmp[i]=cur;
dist[i] = val;
}
}
}
step *= 0.85;
}

for(int i=0 ; i<P ; i++){
if(dist[i]>ret){
ret = dist[i];
ans = tmp[i];
}
}
printf("The safest point is (%.1f, %.1f).\n" , ans.x , ans.y);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: