Algorithm 访问点、算法

Algorithm 访问点、算法,algorithm,data-structures,Algorithm,Data Structures,我正在为考试学习算法和数据结构(我在一个月内掌握了这些),但我无法找到解决这个问题的有效算法: 我们得到了11->5->8->10,我们得到了最小总时间,等于:11 我的第一个想法是按:(时间点,坐标点)对所有点进行字典排序,然后按此顺序访问它们。当然,当第i点和(i+1)点之间有点时,我们可以在访问(i+1)点之前访问它们。但不幸的是,没有理由认为这种贪婪的方法应该奏效,尽管它很难实施。也许我想解决得太快了?n很小,所以我想O(n^2)应该可以 我找到了其他的输入示例,我想这可能会帮助我找到解

我正在为考试学习算法和数据结构(我在一个月内掌握了这些),但我无法找到解决这个问题的有效算法:

我们得到了11->5->8->10,我们得到了最小总时间,等于:11

我的第一个想法是按:(时间点,坐标点)对所有点进行字典排序,然后按此顺序访问它们。当然,当第i点和(i+1)点之间有点时,我们可以在访问(i+1)点之前访问它们。但不幸的是,没有理由认为这种贪婪的方法应该奏效,尽管它很难实施。也许我想解决得太快了?n很小,所以我想O(n^2)应该可以

我找到了其他的输入示例,我想这可能会帮助我找到解决方案。但现在我只看到我必须找到所有可能的$n!$排列

输入示例:

点(也分别由坐标和点时间给出):(0,4),(1,2),(4,5):令人惊讶的是(我认为)我们必须访问它们:0->1->4,因为任何不同的顺序都不满足问题文本中最后一句前一句的条件

积分:(0,7),(1,2),(2,1),(3,4),(4,11),唯一有趣的方式是:2->1->3->0->4,这需要我们10秒


有人能帮忙吗?

首先根据坐标对点进行排序

我建议采用一种动态规划方法,其基础是为0和n-1之间的近值和远值解决以下子问题:

考虑到我们已经在第^个点附近,并且已经访问了近距离和远距离(包括)之间的所有点,那么如果我们有足够的时间访问所有剩余点,那么现在必须是什么时间

当x在0和n-1之间变化时,对于近=远=x,子问题的最大值v(x)给出了问题的答案。如果某些x的v(x)=0,则可以从位置x开始,在“所有点的最大点时间”-v给定的时间内到达所有点

病例之间的复发是基于考虑从第^点左右移动,直到到达第一个尚未覆盖的点。(这将涉及到邻近点或远处点的近邻,因此递归只需要O(1)个计算时间)

有n^2个子问题,因此此方法总体上需要花费O(n^2)的时间

编辑

实现此方法的Python代码:

A=[(0,7), (1,2), (2,1), (3, 4), (4,11)]
A.sort()
M=max(a[1] for a in A)
cache={}
def go(near,far):
    """Given that we are at near and have visited all points in [near..far], 
    (near can be > or < or = far)
    return the latest time that allows us to visit all points, 
    and visit the point near itself."""
    if abs(far-near)==len(A)-1:
        return A[near][1]-1

    key=near,far
    if key in cache:
        return cache[key]

    v=-1
    d = 1 if near<=far else -1
    n = near-d
    if 0<=n<len(A):
        v=go(n,far)-abs(A[n][0]-A[near][0])
    n = far+d
    if 0<=n<len(A):
        v=max(v,go(n,near)-abs(A[n][0]-A[near][0]))

    v=min(v,A[near][1]-1)
    cache[key]=v
    return v

v=max((go(x,x),x) for x in xrange(len(A)))
if v[0]<0:
    print 'Impossible'
else:
    print 'Takes',M-v[0]-1,'seconds starting from point',v[1]
A=[(0,7)、(1,2)、(2,1)、(3,4)、(4,11)]
A.排序()
M=最大值(a中的a为[1]
缓存={}
def go(近、远):
“鉴于我们在附近,并且已经访问了[近..远]的所有点,
(近可以是>或<或=远)
返回允许我们访问所有点的最新时间,
并访问其附近的点
如果abs(远-近)=len(A)-1:
返回[near][1]-1
键=近,远
如果在缓存中输入密钥:
返回缓存[键]
v=-1

d=1,这不等于在图上找到一个最小生成树,其中每个点都是一个节点,顶点是从一个节点移动到另一个节点所需的时间吗?@AdrienPlisson:我不理解你的简化,在这里节点有“生命时间”,它也是一条路径,而不是不同路径的组合。也许我没听清你的想法,可以详细说明一下吗?一种贪婪的方法是按照
(t-CURRENT\u t)-(x-CURRENT\u x)
的升序对未访问的点进行排序。第一个是最贪婪的选择,如果它变为负值,递归就会中断。我没有遵循解决方案,你能更好地解释递归吗?(也许如果我也仔细阅读,我会更容易理解)。我添加了一些示例代码-你可能会发现这比我的英语更容易理解-抱歉!如果我理解正确,@Peter de Rivaz所说的是,对于每个潜在的起点,我们建立了一个可能的范围列表,以使我们开始的点是该范围的端点之一(例如,从点1开始,然后范围是(1,1)、(1,0)、(1,2)等)。对于每个范围,计算从我们的点开始的最新可能时间,以便我们可以覆盖整个范围。该算法使用动态规划来计算这些时间,总共有n^2次。然后,它选择一个解决方案,该解决方案覆盖所有n个具有最新开始时间(=节省的最长时间)的元素