Python + pylab,576个字节
算法:
我解释的问题,因为发现从最短路径(-3,0)至(3,0) ,使得垂直线段的路径上的点连接到的一个点上F(X)不穿过钉子。
在每个存在至少一个钉子的x处,找到钉子在该x处给出的最小上限和最大下限。将这些边界给定的点以及起点和终点视为图上的顶点。如果两个顶点之间的线段落在每个居间x坐标的上限和下限之内,则添加一条具有权重的边,该权重由两个顶点之间的欧式距离确定。在此图上找到最短路径。
具有27个随机点的示例:
(-0.367534, -0.722751), (-0.710649, -0.701412), (1.593101, -0.484983), (1.771199, 0.681435), (-1.878764, -0.491436), (-0.061414, 0.628570), (-0.326483, -0.512950), (0.877878, 0.858527), (1.256189, -0.300032), (1.528120, -0.606809), (-1.343850, -0.497832), (1.078216, 0.232089), (0.930588, -0.053422), (-2.024330, -0.296681), (-2.286014, 0.661657), (-0.009816, 0.170528), (2.758464, 0.099447), (-0.957686, 0.834387), (0.511607, -0.428322), (-1.657128, 0.514400), (1.507602, 0.507458), (-1.469429, -0.239108), (0.035742, 0.135643), (1.194460, -0.848291), (2.345420, -0.892100), (2.755749, 0.061595), (0.283293, 0.558334),
打高尔夫球
for j in R(i&~1)
循环中缩进的几个空格实际上应该是一个制表符。
from pylab import*
P=((3,0),(-3,0))+input()
X=sorted(set(zip(*P)[0]))
l=len(X)*2
if l>4:scatter(*zip(*P[2:]))
f=lambda x:sin(pi*x)+sin(3*pi*x)/2
B=[[max([-9]+[p[1]for p in P if x==p[0]and p[1]<f(x)]),min([9]+[p[1]for p in P if x==p[0]and p[1]>f(x)])]for x in X]
b=zeros(l);b[2:]=inf
v=list(b)
R=range
for i in R(l):
for j in R(i&~1):
A=B[j/2][j&1];D,d=B[i/2][i&1]-A,X[i/2]-X[j/2];K=1;c=b[j]+norm((d,D))
for k in R(j/2+1,i/2):C=A+D/d*(X[k]-X[j/2]);K&=C<B[k][1];K&=C>B[k][0]
if(c<b[i])&K:b[i]=c;v[i]=j,(X[j/2],A)
l-=2
s=P[:1]
while l/2:l,p=v[l];s+=(p,)
plot(*zip(*s))
show()
不打高尔夫球
from pylab import*
P = input()
Xn,Yn = zip(*P)
X = set(Xn+(3,-3))
f = lambda x:sin(pi*x)+sin(3*pi*x)/2
ylb = {x: max([-9]+[p[1] for p in P if p[0] == x and p[1] < f(x)]) for x in X}
yub = {x: min([9]+[p[1] for p in P if p[0] == x and p[1] > f(x)]) for x in X}
ylb[-3] = yub[3] = ylb[3] = 0
X = sorted(X)
l = len(X)
best = zeros((l,2))
best[1:] = inf
prev = [ [0,0] for i in range(l) ]
for i in range(l): # calculate min path to X[i] lb or ub
for ib in 0,1:
for j in range(i): # point to come from
for jb in 0,1:
Y2, Y1 = (ylb, yub)[ib][X[i]], (ylb, yub)[jb][X[j]]
dy,dx = Y2 - Y1, X[i] - X[j]
if all([Y1 + dy/dx*(x - X[j]) < yub[x] and Y1 + dy/dx*(x - X[j]) > ylb[x] for x in X[j+1:i]]):
c = best[j][jb] + (dy**2+dx**2)**.5
if c < best[i][ib]:
best[i][ib] = c
prev[i][ib] = j, jb, (X[j], Y1)
j, jb = l-1,0
pts = [(3,0)]
while j:
j, jb, p = prev[j][jb]
pts += [p]
plot(*zip(*pts))
scatter(Xn,Yn)
show()