Project Euler 262
Project Euler 262
题目
Mountain Range
The following equation represents the continuous topography of a mountainous region, giving the elevation h at any point \((x,y)\):
\[h = \left(5000 - \frac{x^2 + y^2 + xy}{200} + \frac{25(x + y)}2\right) \cdot e^{-\left|\frac{x^2 + y^2}{1000000} - \frac{3(x + y)}{2000} + \frac 7 {10}\right|}\]
A mosquito intends to fly from \(A(200,200)\) to \(B(1400,1400)\), without leaving the area given by \(0\le x,y\le1600\).
Because of the intervening mountains, it first rises straight up to a point \(A'\), having elevation \(f\).
Then, while remaining at the same elevation \(f\), it flies around any obstacles until it arrives at a point \(B'\) directly above \(B\).
First, determine \(f_{\min}\) which is the minimum constant elevation allowing such a trip from \(A\) to \(B\), while remaining in the specified area.
Then, find the length of the shortest path between \(A'\) and \(B'\), while flying at that constant elevation \(f_{\min}\).
Give that length as your answer, rounded to three decimal places.
Note: For convenience, the elevation function shown above is repeated below, in a form suitable for most programming languages:
1 | h=(5000-0.005*(x*x+y*y+x*y)+12.5*(x+y))*exp(-abs(0.000001*(x*x+y*y)-0.0015*(x+y)+0.7)) |
解决方案
令\(p(x,y)=5000 - \dfrac{x^2 + y^2 + xy}{200} + \dfrac{25(x + y)}{2},g(x,y)=\dfrac{x^2 + y^2}{1000000} - \dfrac{3(x+y)}{2000} + \dfrac{7}{10}\),那么有\(h(x, y) = p(x,y)\cdot e^{-|g(x,y)|}.\)
此外还需要注意的一点是,\(h(x,y)=h(y,x).\)
\(h(x,y)\)的图像和等高线图如下图所示。所使用的 Mathematica 代码如下:
1 | p[x_, y_] := 5000 - (x^2 + y^2 + x*y)/200 + (25*(x + y))/2; |


若在恒定高度 \(f\) 飞行,则蚊子在平面上允许经过的点必须满足:\(h(x,y)\le f\).
因此对任意 \(f\),可把\(\Omega_f=\{(x,y)\in[0,1600]^2:\ h(x,y)>f\}\)视为“山体障碍”。
可飞区域为\(D_f=[0,1600]^2\setminus\Omega_f.\)
随着 \(f\) 增大,障碍 \(\Omega_f={h>f}\) 单调缩小,连通性只会“从不连通变为连通”,并在某个临界值首次连通。
在临界时刻\(f=f_{\min}\),“从不可连通到可连通”通常发生在一个瓶颈被刚好打开的瞬间。对于连续地形的等高线结构,这个瞬间对应两种典型事件之一:
- 障碍集合 \(\Omega_f\) 自身发生拓扑变化(比如出现/消失一个洞、两个分支接触等);
- 障碍集合 \(\Omega_f\) 与边界 \([0,1600]^2\) 的边界发生“相切接触”,从而堵住或打开通道。
本题的地形形态(经典解法所依赖的事实)属于第 2 类:临界时障碍的边界 \({h=f_{\min}}\) 恰好与正方形边界相切,形成“刚好卡住/刚好放开”的狭口,这在我们图中可以观察得出。
因此,我们假设,这个相切点落在边界 \(y=0\) 上,记为\(S=(x_0,0).\)
若 \(\Gamma\) 在边界处“刚好接触”而不穿出边界,则沿边界方向高度必须达到局部极值。对边界 (y=0) 而言,相切点满足\(\displaystyle{x_0=\arg\max_{x\in[0,1600]} h(x,0)}\),那么就有\(f_{\min}=h(x_0,0)\).
固定高度 \(f_{\min}\) 后,障碍边界就是等高线\(\Gamma={(x,y): h(x,y)=f_{\min}}\).
1 | p[x_, y_] := 5000 - (x^2 + y^2 + x*y)/200 + (25*(x + y))/2; |
在欧氏平面中,绕开光滑障碍的最短路满足经典几何性质:
- 在可行区域内部(未贴着障碍边界)的部分,最短路一定是直线段;
- 最短路与障碍边界的连接点必须满足相切条件:若不是相切,可在局部“削去拐角”得到更短路径,矛盾。
因此,最短路径必可表示为:\(A \rightarrow T_A \rightarrow T_B \rightarrow B\):其中\(A \rightarrow T_A, T_B \rightarrow B\)均为直线段,\(T_A \rightarrow T_B\),且中间一段\(T_A,T_B\in\Gamma\) 沿着等高线 \(\Gamma\) 绕行,并在连接点 \(T_A\)、\(T_B\) 处与 \(Γ\) 满足相切条件(即直线段在该点与 \(\Gamma\) 的切线方向一致)。
因此,\(T_A,T_B\)满足连线方向应当与法向量正交,即\(\nabla h(T_A)\cdot \overrightarrow{T_AA}=0,\nabla h(T_B)\cdot \overrightarrow{T_BB}=0.\)
为计算在\(\Gamma\)上的固定目标切点,不妨假设 \(G\in\{A,B\}.\)
对等高线上的点 \(X\) 定义\(\Phi(X)=\nabla h(X)\cdot \overrightarrow{GX}.\)当\(\Phi(X)=0\)时,连线 \(GX\) 与等高线在 \(X\) 处满足切线条件(也就是连线方向落在切空间内,等价于与法向量正交)。
因此,从瓶颈点 \(S\) 沿 \(\Gamma\) 走动时,只要监控 \(\Phi\) 的符号变化,就能找到“从尚未切到已经越过”的过零点;再对该过零区间做二分,就能把切点逼近到任意精度。
最终,用很小步长沿某个方向推进一个坐标,再在新竖线或新横线上解方程\(h(\cdot,\cdot)=f_{\min}\)把点“拉回”到等高线。因为步长小,求根区间很短,用二分法非常稳健。相邻点的欧氏距离累加就是弧长近似。
分别得到:
- 从 \(S\) 到 \(T_A\) 的等高线弧长记为 \(L_A^{\text{arc}}\),直线段长度记为 \(|AT_A|\);
- 从 \(S\) 到 \(T_B\) 的等高线弧长记为 \(L_B^{\text{arc}}\),直线段长度记为 \(|BT_B|\)。
总最短路长度为\(L=(L_A^{\text{arc}}+|AT_A|)+(L_B^{\text{arc}}+|BT_B|).\)
代码
1 | import math # 导入数学库:用到 exp / abs / hypot 等基础函数 |