BZOJ 3695 滑行 迭代+二分

9 篇文章 0 订阅
9 篇文章 0 订阅

题目大意:给定一个n层的区域,从左下角走到右上角,每个区域的高度和速度都不同,问怎么走最快

由于我并不知道光路最速原理所以我写了迭代+二分23333

首先易知每一层的路线都一定是一条直线

我们考虑只有两层的情况 由于左下角和右上角固定 因此我们可以三分确定中间的转折点的位置

或者可以写出时间关于转折点坐标的函数关系 求导之后二分 这个更快一些

那么现在是多层 我们这样搞:

每次迭代,枚举1~n-1的每个转折点,对于第i个转折点确定第i-1个点和第i+1个点的位置,二分确定第i个转折点

这样迭代4000次就能出结果了= = 果断BZ倒数第一

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 110
#define EPS 1e-3
using namespace std;
int n;
double X[M],Y[M],v[M];
double sqr(double x)
{
	return x*x;
}
double Bisection(int i)
{
	double l=X[i-1],r=X[i+1];
	while(r-l>EPS)
	{
		double mid=(l+r)/2;
		double temp=(mid-X[i-1])/sqrt(sqr(mid-X[i-1])+sqr(Y[i]))/v[i]+(mid-X[i+1])/sqrt(sqr(mid-X[i+1])+sqr(Y[i+1]))/v[i+1];
		if(temp>0)
			r=mid;
		else
			l=mid;
	}
	return (l+r)/2;
}
int main()
{
	int i,j;
	cin>>n;cin>>X[n];
	for(i=1;i<=n;i++)
		scanf("%lf",&Y[i]);
	for(i=1;i<=n;i++)
		scanf("%lf",&v[i]);
	for(i=1;i<n;i++)
		X[i]=X[n]/n*i;
	double delta=0;
	for(i=1;i<=4000; ++i)
	{
		delta=0;
		for(j=1;j<n;j++)
		{
			double temp=X[j];
			X[j]=Bisection(j);
			delta+=fabs(temp-X[j]);
		}
		if(delta<EPS)
			break;
	}
	double ans=0;
	for(i=1;i<=n;i++)
		ans+=sqrt(sqr(X[i]-X[i-1])+sqr(Y[i]))/v[i];
	printf("%.3lf\n",ans);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值