poj1379+POJ2420+hdu3932(最短距离+费马点+模拟淬火算法)

Run Away

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 5632   Accepted: 1729

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 completely harmless at the first sight. But when activated, they start to throw out very
hot java, uh ... pardon, lava. Unfortunately, all known paths to the Center Room (where the Sarcophagus is) contain a trigger that activates the trap. The ACM were not able to avoid that. But they have carefully monitored the positions of all the holes. So
it is important to find the place in the Large Room that has the maximal distance from all the holes. This place is the safest in the entire room and the archaeologist has to hide there.

Input

The input consists of T test cases. The number of them (T) is given on the first line of the input file. Each test case begins with a line containing three integers X, Y, M separated by space. The numbers satisfy conditions: 1
<= X,Y <=10000, 1 <= M <= 1000. The numbers X and Yindicate the dimensions of the Large Room which has a rectangular shape. The number M stands for the number of holes. Then exactly M lines follow, each containing two integer numbers Ui and Vi (0 <= Ui <=
X, 0 <= Vi <= Y) indicating the coordinates of one hole. There may be several holes at the same position.

Output

Print exactly one line for each test case. The line should contain the sentence "The safest point is (P, Q)." where P and Qare the coordinates of the point in the room that has the maximum distance from the nearest hole, rounded
to the nearest number with exactly one digit after the decimal point (0.05 rounds up to 0.1).

Sample Input

3
1000 50 1
10 10
100 100 4
10 10
10 90
90 10
90 90
3000 3000 4
1200 85
63 2500
2700 2650
2990 100

Sample Output

The safest point is (1000.0, 50.0).
The safest point is (50.0, 50.0).
The safest point is (1433.0, 1669.8).

Source

题解:

昨天在网上浏览博客,无意看见有个ACMer交了这题并注明模拟淬火算法,由于在人工智能课上老师提到过这类演化算法-模拟淬火算法。感慨ACM在线OJ还能用模拟淬火算法这类概率算法,于是眼前一亮,有登上好久没有刷题的POJ了,看了道题。

题意是要求到给定n个点的最小距离最大的点,且点限定在给定矩形内。要是一维的,直接三分找极值即可;在平面上就不太好处理了。且这样的点可能不只一个,到底取谁都要考虑。前人提供了模拟淬火算法,直接搞定了。大致步骤如下:

1、随机选取一个合适的控制条件T作为开始

2、随机选取P个起始点,作为可行解

3、分别依据内能更新这P个可行解

4、减小控制条件T,直到终止条件

下面是代码:

#include<iostream>
#include<cmath>
#include<ctime>
#include<cstdio>
using namespace std;

const int MAXN=1000+100;
const int KMEAN=30;
const double INF=1<<30;
const double eps=1e-8;
const double PI=3.141592653;
int x,y,n;
struct Point
{
	double x,y;
}myPoint[MAXN],myK[KMEAN];
double dis[KMEAN];

double GetMinDis(double tx,double ty)
{
	double minDis=INF,temp;
	for(int i=0;i<n;i++)
	{
      	temp=sqrt((tx-myPoint[i].x)*(tx-myPoint[i].x)+(ty-myPoint[i].y)*(ty-myPoint[i].y));
		if(temp<minDis)
	    	minDis=temp;
	}
	return minDis;
}

int main()
{
	int cas,i,j;
	double temp;
	scanf("%d",&cas);
	while(cas--)
	{
		scanf("%d%d%d",&x,&y,&n);
		srand((unsigned)time(NULL));
		for(i=0;i<n;i++)
			scanf("%lf%lf",&myPoint[i].x,&myPoint[i].y);

		for(i=0;i<KMEAN;i++)
		{
			dis[i]=INF;
			myK[i].x=rand()%10001/10000.0*x;
			myK[i].y=rand()%10001/10000.0*y;
		}
		for(i=0;i<KMEAN;i++)
		   dis[i]=GetMinDis(myK[i].x,myK[i].y);

		double theta,delta=1.0*(x>y?x:y)/sqrt(1.0*n);
		while(delta>eps)
		{
			for(i=0;i<KMEAN;i++)
			{
				double nx=myK[i].x,ny=myK[i].y;
				for(j=0;j<KMEAN;j++)
				{
					double tx,ty;
					theta=double(rand()%10001)/10000.0*2*PI;
					tx=nx+delta*cos(theta);
					ty=ny+delta*sin(theta);
					if(tx<0||tx>x||ty<0||ty>y)
						continue;

					temp=GetMinDis(tx,ty);
					if(temp>dis[i])
					{
						myK[i].x=tx;
						myK[i].y=ty;
						dis[i]=temp;
					}
				}
			}
			delta=0.8*delta;
		}

		int id=-1;
		temp=-INF;
		for(i=0;i<KMEAN;i++)
		{
			if(dis[i]>temp)
			{
				temp=dis[i];
				id=i;
			}
		}
		printf("The safest point is (%.1lf, %.1lf).\n",myK[id].x,myK[id].y);
	}
	return 0;
}

下面是相似的题

A Star not a Tree?

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 3274   Accepted: 1666

Description

Luke wants to upgrade his home computer network from 10mbs to 100mbs. His existing network uses 10base2 (coaxial) cables that allow you to connect any number of computers together in a linear arrangement. Luke is particulary proud
that he solved a nasty NP-complete problem in order to minimize the total cable length.

Unfortunately, Luke cannot use his existing cabling. The 100mbs system uses 100baseT (twisted pair) cables. Each 100baseT cable connects only two devices: either two network cards or a network card and a hub. (A hub is an electronic device that interconnects
several cables.) Luke has a choice: He can buy 2N-2 network cards and connect his N computers together by inserting one or more cards into each computer and connecting them all together. Or he can buy N network cards and a hub and connect each of his N computers
to the hub. The first approach would require that Luke configure his operating system to forward network traffic. However, with the installation of Winux 2007.2, Luke discovered that network forwarding no longer worked. He couldn‘t figure out how to re-enable
forwarding, and he had never heard of Prim or Kruskal, so he settled on the second approach: N network cards and a hub.

Luke lives in a loft and so is prepared to run the cables and place the hub anywhere. But he won‘t move his computers. He wants to minimize the total length of cable he must buy.

Input

The first line of input contains a positive integer N <= 100, the number of computers. N lines follow; each gives the (x,y) coordinates (in mm.) of a computer within the room. All coordinates are integers between 0 and 10,000.

Output

Output consists of one number, the total length of the cable segments, rounded to the nearest mm.

Sample Input

4
0 0
0 10000
10000 10000
10000 0

Sample Output

28284

题解:

本题与上面那题的唯一区别就是目的函数不同,此处为最短距离和,上面为最短距离的最大者,模拟淬火算法。直接贴代码的。

#include<iostream>
#include<cmath>
#include<ctime>
#include<cstdio>
using namespace std;

const int MAXN=100+10;
const int KMEAN=30;
const double INF=1<<30;
const double eps=1e-8;
const double PI=3.141592653;
double x=10000.0,y=10000.0;
int n;
struct Point
{
	double x,y;
}myPoint[MAXN],myK[KMEAN];
double dis[KMEAN];

double GetMinDis(double tx,double ty)
{
	double temp=0;
	for(int i=0;i<n;i++)
	{
      	temp+=sqrt((tx-myPoint[i].x)*(tx-myPoint[i].x)+(ty-myPoint[i].y)*(ty-myPoint[i].y));
	}
	return temp;
}

int main()
{
	int i,j;
	double temp;
	while(scanf("%d",&n)!=EOF)
	{
		srand((unsigned)time(NULL));
		for(i=0;i<n;i++)
			scanf("%lf%lf",&myPoint[i].x,&myPoint[i].y);

		for(i=0;i<KMEAN;i++)
		{
			dis[i]=INF;
			myK[i].x=rand()%10001/10000.0*x;
			myK[i].y=rand()%10001/10000.0*y;
		}
		for(i=0;i<KMEAN;i++)
		   dis[i]=GetMinDis(myK[i].x,myK[i].y);

		double theta,delta=10000.0/sqrt(1.0*n);
		while(delta>eps)
		{
			for(i=0;i<KMEAN;i++)
			{
				double nx=myK[i].x,ny=myK[i].y;
				for(j=0;j<KMEAN;j++)
				{
					double tx,ty;
					theta=double(rand()%10001)/10000.0*2*PI;
					tx=nx+delta*cos(theta);//可改变方向
					ty=ny+delta*sin(theta);
					temp=GetMinDis(tx,ty);
					if(temp<dis[i])
					{
						myK[i].x=tx;
						myK[i].y=ty;
						dis[i]=temp;
					}
				}
			}
			delta=0.98*delta;
		}
		temp=INF;
		for(i=0;i<KMEAN;i++)
		{
			if(dis[i]<temp)
			{
				temp=dis[i];
			}
		}
		printf("%.0lf\n",temp);
	}
	return 0;
}

下面这题是求最小圆覆盖。

Groundhog Build Home

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 1397    Accepted Submission(s): 625

Problem Description

Groundhogs are good at digging holes, their home is a hole, usually a group of groundhogs will find a more suitable area for their activities and build their home at this area .xiaomi has grown up, can no longer live with its parents.so
it needs to build its own home.xiaomi like to visit other family so much, at each visit it always start from the point of his own home.Xiaomi will visit all of the groundhogs‘ home in this area(it will chose the linear distance between two homes).To save energy,xiaomi
would like you to help it find where its home built,so that the longest distance between xiaomi‘s home and the other groundhog‘s home is minimum.

Input

The input consists of many test cases,ending of eof.Each test case begins with a line containing three integers X, Y, N separated by space.The numbers satisfy conditions: 1 <= X,Y <=10000, 1 <= N<= 1000. Groundhogs acivity at a rectangular
area ,and X, Y is the two side of this rectangle, The number N stands for the number of holes.Then exactly N lines follow, each containing two integer numbers xi and yi (0 <= xi <= X, 0 <= yi <= Y) indicating the coordinates of one home.

Output

Print exactly two lines for each test case.The first line is the coordinate of xiaomi‘s home which we help to find. The second line is he longest distance between xiaomi‘s home and the other groundhog‘s home.The output round to the
nearest number with exactly one digit after the decimal point (0.05 rounds up to 0.1).

Sample Input

1000 50 1
10 10
1000 50 4
0 0
1 0
0 1
1 1

Sample Output

(10.0,10.0).
0.0
(0.5,0.5).
0.7

题解:

题意是要求到给定n个点的最大距离最小的点,且点限定在给定矩形内,对应数学模型最小点覆盖。贴段代码:

#include<iostream>
#include<cmath>
#include<ctime>
#include<cstdio>
using namespace std;

const int MAXN=1000+100;
const int KMEAN=30;
const double INF=1<<30;
const double eps=1e-8;
const double PI=3.141592653;
int x,y,n;
struct Point
{
	double x,y;
}myPoint[MAXN],myK[KMEAN];
double dis[KMEAN];

double GetMaxDis(double tx,double ty)
{
	double maxDis=-INF,temp;
	for(int i=0;i<n;i++)
	{
      	temp=sqrt((tx-myPoint[i].x)*(tx-myPoint[i].x)+(ty-myPoint[i].y)*(ty-myPoint[i].y));
		if(temp>maxDis)
	    	maxDis=temp;
	}
	return maxDis;
}

int main()
{
	int i,j;
	double temp;
	while(scanf("%d%d%d",&x,&y,&n)!=EOF)
	{
		srand((unsigned)time(NULL));
		for(i=0;i<n;i++)
			scanf("%lf%lf",&myPoint[i].x,&myPoint[i].y);

		for(i=0;i<KMEAN;i++)
		{
			dis[i]=INF;
			myK[i].x=rand()%10001/10000.0*x;
			myK[i].y=rand()%10001/10000.0*y;
		}
		for(i=0;i<KMEAN;i++)
		   dis[i]=GetMaxDis(myK[i].x,myK[i].y);

		double theta,delta=1.0*(x>y?x:y)/sqrt(1.0*n);
		while(delta>eps)
		{
			for(i=0;i<KMEAN;i++)
			{
				double nx=myK[i].x,ny=myK[i].y;
				for(j=0;j<KMEAN;j++)
				{
					double tx,ty;
					theta=double(rand()%10001)/10000.0*2*PI;
					tx=nx+delta*cos(theta);
					ty=ny+delta*sin(theta);
					if(tx<0||tx>x||ty<0||ty>y)
						continue;

					temp=GetMaxDis(tx,ty);
					if(temp<dis[i])
					{
						myK[i].x=tx;
						myK[i].y=ty;
						dis[i]=temp;
					}
				}
			}
			delta=0.8*delta;
		}

		int id=-1;
		temp=INF;
		for(i=0;i<KMEAN;i++)
		{
			if(dis[i]<temp)
			{
				temp=dis[i];
				id=i;
			}
		}
		printf("(%.1lf,%.1lf).\n%.1lf\n",myK[id].x,myK[id].y,temp);
	}
	return 0;
}

poj1379+POJ2420+hdu3932(最短距离+费马点+模拟淬火算法),布布扣,bubuko.com

时间: 2024-10-19 03:56:37

poj1379+POJ2420+hdu3932(最短距离+费马点+模拟淬火算法)的相关文章

poj2069+hud3007(点的最小球(圆)覆盖+模拟淬火算法)

Super Star Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3198   Accepted: 853   Special Judge Description During a voyage of the starship Hakodate-maru (see Problem 1406), researchers found strange synchronized movements of stars. Havi

多校第一场 费马小定理+模拟+组合数学

A题:Couple doubi 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4861 这题逗逼了,刚开始根本就没什么思路,刚开始看题的时候有点像费马小定理,但是这个定理我只知道,然后没用过.看了下定义,有点不一样的是反着的,然后反着的我又不会转化,尼玛,就这样错过了最好的解题方法.然后队友又理解错题意了.WA了多发,然后我重新看了下题意,然后队友才发觉理解错题意了,然后找了规律才A. 代码比较短,就不贴了,真的写吧. if(k/(p-1)&1) pu

【模板】模拟退火 费马点以及最小球覆盖

最近学了一波模拟退火.个人感觉,就是随机算法,然后我们的目标点,一开始温度T高的时候会移动的剧烈,T小的时候移动的缓和(所以这就是为什么每一次移动的距离都是乘T).然后真正的模拟退火是如果当前的tem比ans优,那就毫不犹豫地接受,否则则以一定概率接受.也就是那个exp(dE/T)> rand 那个. 然后还有爬山算法,就是只会一直找更优解,不接受差解,具体就是在模拟退火基础上,一直找最优解,找不到就降温(所以会陷入局部最优解的坑).在网上嫖了一份代码(https://blog.csdn.net

hdu 4704 Sum (整数和分解+快速幂+费马小定理降幂)

题意: 给n(1<n<),求(s1+s2+s3+...+sn)mod(1e9+7).其中si表示n由i个数相加而成的种数,如n=4,则s1=1,s2=3.                         (全题文末) 知识点: 整数n有种和分解方法. 费马小定理:p是质数,若p不能整除a,则 a^(p-1) ≡1(mod p).可利用费马小定理降素数幂. 当m为素数,(m必须是素数才能用费马小定理) a=2时.(a=2只是题中条件,a可以为其他值) mod m =  *      //  k=

HDU 1098 Ignatius&#39;s puzzle 费马小定理+扩展欧几里德算法

题目大意: 给定k,找到一个满足的a使任意的x都满足 f(x)=5*x^13+13*x^5+k*a*x 被65整除 推证: f(x) = (5*x^12 + 13 * x^4 + ak) * x 因为x可以任意取 那么不能总是满足 65|x 那么必须是 65 | (5*x^12 + 13 * x^4 + ak) 那么就是说 x^12 / 13 + x^4 / 5 + ak / 65 正好是一个整数 假设能找到满足的a , 那么将 ak / 65 分进x^12 / 13 + x^4 / 5中得到

【Lucas定理/费马小定理/中国剩余定理/扩展欧几里得】[BZOJ 1951] 古代猪文

[Description] 求 [Solution] 容易得到, 所以,重点在怎么求 如果是p-1是个质数,我们可以用sqrt(n)的时间枚举所有d,用Lucas定理分别计算求和即可. 但是我们发现p-1=2*3*4679*35617,并不是一个质数,所以Lucas定理不能用了吗?并不,我们可以算出这个合式分别对2.3.4679.35617的模值,写出四个同余方程,再用孙子定理求解即可.注意特判g==p的情况,此时费马小定理不成立,ans=0. [Code] #include<cmath> #

hdu 4549 (矩阵快速幂+费马小定理)

题意:已知F0=a,F1=b,Fn=Fn-1*Fn-2,给你a,b,n求Fn%1000000007的值 思路:我们试着写几组数 F0=a F1=b F2=a*b F3=a*b2 F4=a2*b3 F5=a3*b5 我们发现a,b的系数其实是斐波那契数列,我们只需用矩阵快速幂求出相应系数就行,但是 这个系数随着增长会特别大,这时我们需要利用费马小定理进行降幂处理 费马小定理 ap-1≡1(mod p) 代码: #include <iostream> #include <cmath>

hdu1098费马小定理

Ignatius's puzzle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 9783    Accepted Submission(s): 6839 Problem Description Ignatius is poor at math,he falls across a puzzle problem,so he has no

数论学习之费马与欧拉

数论复习之费马与欧拉 QB_UDG  2016年11月8日10:16:18 1.费马小定理 Fermat Theory 如果 p是素数,且a与p互质,即gcd(a,p)=1   那么(a^p-1) ≡ 1 (mod p) 应用: 求乘法逆元   乘法逆元: (x*x')≡ 1 (mod p) 称x'为x模p的乘法逆元 (注意,一定要是余1) 逆元 :(b/a) (mod n) = (b * x) (mod n). x表示a的逆元.并且 a*x ≡ 1 (mod n)  注意:只有当a与n互质的时