【POJ1379】Run Away 模拟退火

#include <stdio.h>
int main()
{
	puts("转载请注明出处[vmurder]谢谢");
	puts("网址:blog.csdn.net/vmurder/article/details/43526827");
}

题意:

给若干个点,现在求一个点,使它到离它最近的点尽量远。

题解:

我写的是模拟退火先玩一会,然后小幅度爬爬山。

种子的采用是20134858

是生日^人的名字首字母hash。

诶可算A了,看来我脸还不是太黑。

代码:

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 10100
#define dinf 1e18
#define eps 1e-5
#define down 0.998
using namespace std;
double n,m;
struct Point // 点
{
	double x,y,z; // 坐标、该点作为结束点的答案。
	Point(double _x=0.0,double _y=0.0):x(_x),y(_y){}
	bool in()
	{
		if(x<0.0||x>n)return 0;
		if(y<0.0||y>m)return 0;
		return 1;
	}
}P[N],now,ans;

int p;

// 随机函数,随机出来一个0~1之间的小数
inline double Rand(){return ((double)(rand()%1000+1.0))/1000.0;}

// 其实找初始点时最好找平均数之类
inline void init()
{
	double tempx=0.0,tempy=0.0;
	for(int i=1;i<=p;i++)tempx+=P[i].x,tempy+=P[i].y;
		tempx+=2*n,tempy+=2*m;
	now=Point(tempx/(p+4),tempy/(p+4));
//	now=Point(n/2,m/2);
	ans.z=0.0;
}

// 计算两点间欧拉距离
inline double calc(const Point &a,const Point &b)
{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}

// 计算所有点到点a的欧拉距离最小值并更新ans
inline double Calc(Point &a)
{
	a.z=dinf;
	for(int i=1;i<=p;i++)a.z=min(a.z,calc(P[i],a));
	if(a.z>ans.z)ans=a;
	return a.z;
}
Point newpos(double T,const Point &a)
{
	double alp=2.0*acos(-1.0)*Rand(); // 角度
	return Point(a.x+T*cos(alp)*Rand(),a.y+T*sin(alp)*Rand());
}
// 模拟退火
void Std_Anne() // [S]imula[t]e[d] [Anne]aling
{
	 //  温度,或者说转移半径
	for(double T=sqrt(n*n+m*m)*0.42;T>eps;T*=down) // 每次降温
	{
		Point next=newpos(T,now);
		// next为转移后的点
		if(next.in())
		{
			double dis=Calc(next)-Calc(now);
			if(exp(dis/T)>Rand()-eps)now=next;
		}
	}
}

// 爬山
void ioi()  // Cl[i]mb M[o]unta[i]n
{
	double T=0.5,alp;
	for(int i=1;i<=50000;i++)
	{
		Point next=newpos(T,ans);
		if(next.in())
		{
			double dis=Calc(next)-Calc(now);
			if(dis>0)now=next;
		}
	}
}

int main()
{
	freopen("test.in","r",stdin);
	srand(20134858);
	int i,j,k,g;
	for(scanf("%d",&g);g--;)
	{
		scanf("%lf%lf%d",&n,&m,&p);
		for(i=1;i<=p;i++)
			scanf("%lf%lf",&P[i].x,&P[i].y);
		init();
		Std_Anne();
		ioi();
		printf("The safest point is (%.1lf, %.1lf).\n",ans.x,ans.y);
	}
	return 0;
}
时间: 2024-10-03 14:45:29

【POJ1379】Run Away 模拟退火的相关文章

Run Away 模拟退火

Run Away Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description One of the traps we will encounter in the Pyramid is located in the Large Room. A lot of small holes are drilled into the floor. They look

【模拟退火】poj1379 Run Away

题意:平面上找一个点,使得其到给定的n个点的距离的最小值最大. 模拟退火看这篇:http://www.cnblogs.com/autsky-jadek/p/7524208.html 这题稍有不同之处仅有:多随机几个初始点,以增加正确率. 另:WA了几百遍竟然是因为最后输出了-0.0这样的值…… #include<cstdio> #include<cmath> #include<algorithm> #include<cstdlib> using namesp

【BZOJ1844/2210】Pku1379 Run Away 模拟退火

[BZOJ1844/2210]Pku1379 Run Away 题意:矩形区域中有一堆点,求矩形中一个位置使得它到所有点的距离的最小值最大. 题解:模拟退火的裸题,再调调调调调参就行了~ #include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include <cstdlib> using namespace std; const int maxn=10

PKU 1379 Run Away(模拟退火算法)

题目大意:原题链接 给出指定的区域,以及平面内的点集,求出一个该区域内一个点的坐标到点集中所有点的最小距离最大. 解题思路:一开始想到用随机化算法解决,但是不知道如何实现.最后看了题解才知道原来是要用模拟退火算法解决. 不过个人感觉这个算法的实现过程中仍然采用了随机化算法.二者均属于概率算法.  参考链接 Point Goto_Rand_Dir(double key,Point temp)函数中,Point temp必须得定义在参数中,不能定义在函数内部, 否则temp没有初始值,无法进行后面的

POJ 1379 Run Away 模拟退火

一开始写了一发很快的,发现一会能过一会不能,貌似有点悬,毕竟是随机算法. 后来重写了一发迭代5遍的,基本上把把AC了= = 模拟退火果然是一种不是很靠谱的算法. #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <cstdlib> #include <ctime> using namespace std; const

poj 1379 Run Away 模拟退火 难度:1

Run Away Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6482   Accepted: 1993 Description One of the traps we will encounter in the Pyramid is located in the Large Room. A lot of small holes are drilled into the floor. They look complet

poj1379 Run Away

传送门:http://poj.org/problem?id=1379 [题解] 题目大意:求(0,0)->(X,Y)内的一个点,使得这个点到给定的n个点的最小距离最大. 模拟退火 一开始可以先把4个顶点加入. 调调参就过样例了. 然后就过了 # include <math.h> # include <stdio.h> # include <stdlib.h> # include <string.h> # include <iostream>

poj1379 模拟退火

1 //Accepted 220 KB 829 ms 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <ctime> 6 #include <cstdlib> 7 #include <iostream> 8 using namespace std; 9 const int iL=30; 10 const int iP=30; 11 const

POJ 1379 Run Away 【基础模拟退火】

题意:找出一点,距离所有所有点的最短距离最大 二维平面内模拟退火即可,同样这题用最小圆覆盖也是可以的. Source Code: //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <fstream> #include <cstring> #include <cm