2018 CodeM初赛B轮:D.神奇盘子

本文介绍了一个有趣的问题:一只大象位于一个圆形盘子上,并能在盘子直径两端瞬间传送。通过模拟退火算法寻找大象从起点到终点的最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链接:https://www.nowcoder.com/acm/contest/151/D
来源:牛客网

题目描述

有一个神奇的盘子,形状为圆形。盘子上面爬着一个大象(视作一个点)。由于现实的扭曲,当大象在盘子某个直径的一端的时候,可以瞬间传送至直径的另一端。现在大象想去盘子上另外一点,问他最少需要移动多少距离。传送不计距离。

输入描述:

第一行一个整数r(1 <= r <= 1000)代表盘子的半径。
接下来两行两个整点分别代表大象所在的位置和大象目标的位置坐标。保证两个点都在圆内(可能在边界上),圆心在点(0, 0)上。

输出描述:

输出一个实数,代表大象最短需要移动多少距离。和标程相对或绝对相差1e-6都算正确。


随机暴力能过就好

直接对极坐标模拟退火找到最优的点,精确度还是很高的


#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define PI acos(-1.0)
double x, y, x1, yl, x2, y2, R;
double Dis(double a, double b, double c, double d)
{
	return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
void Jud(double k)
{
	while(k>=PI)
		k -= PI;
	if(k>=PI/2 || k<=-PI/2)
		y = R*sin(k), x = -sqrt(R*R-y*y);
	else
		y = R*sin(k), x = sqrt(R*R-y*y);
}
double Rand()
{
    return rand()%1000/1000.0;
}
double Do(double p)
{
	Jud(p);
	return Dis(x, y, x1, yl)+Dis(-x, -y, x2, y2);
}
double SA(double T)
{
	double dx, now, temp;
	now = 0; Do(now);
	while(T>0.0001)
	{
		temp = now+T*(Rand()*2-1);
		dx = Do(now)-Do(temp);
		if(dx>0)
			now = temp;
		T = T*0.9993;
	}
	return Do(now);
}
int main(void)
{
	scanf("%lf%lf%lf%lf%lf", &R, &x1, &yl, &x2, &y2);
	printf("%.10f\n", min(Dis(x1, yl, x2, y2), SA(PI/2)));
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值