Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用曼哈顿距离的多个点之间的最短路径_Java_Algorithm_Performance_Optimization - Fatal编程技术网

Java 使用曼哈顿距离的多个点之间的最短路径

Java 使用曼哈顿距离的多个点之间的最短路径,java,algorithm,performance,optimization,Java,Algorithm,Performance,Optimization,这是我在学校得到的作业之一。任何形式的建议都将不胜感激 我有一张街道地图,每个十字路口都用坐标=整数的元组(x,y)表示。两个坐标之间的长度等于它们之间的曼哈顿距离。我是出租车司机,我有每个客户的坐标和他们想去的地方的坐标,起始坐标和我可以在车内拥有的最大客户数。我需要找到最短的路径,将所有客户送至目的地。客户只能在最终目的地下车结果是客户的顺序,出租车司机必须在其中挑选/丢弃客户 我当前的解决方案使用递归查找它们的所有路径,比较它们的长度并返回最短的路径。问题是,它太慢了。它需要在一秒钟内完成

这是我在学校得到的作业之一。任何形式的建议都将不胜感激

我有一张街道地图,每个十字路口都用坐标=整数的元组(x,y)表示。两个坐标之间的长度等于它们之间的曼哈顿距离。我是出租车司机,我有每个客户的坐标他们想去的地方的坐标,起始坐标和我可以在车内拥有的最大客户数。我需要找到最短的路径,将所有客户送至目的地。客户只能在最终目的地下车结果是客户的顺序,出租车司机必须在其中挑选/丢弃客户

我当前的解决方案使用递归查找它们的所有路径,比较它们的长度并返回最短的路径。问题是,它太慢了。它需要在一秒钟内完成

谢谢你的帮助

编辑1: 功能:滑行=当前滑行坐标,starti=所有客户的上车坐标(starti[0]=客户1的上车坐标),cilji=所有客户的终点站(cilji[0]=客户1的下车坐标),left=开车前往目的地的客户数量,索引=只是为了得出最终结果,n=出租车上的最大客户数量,atm=当时车上的客户数量

public static int abs(int n) {
    if (n < 0) {
        return -n;
    }
    return n;
}
public static int razdalja(int[] a, int[] b) {
    return abs(a[0] - b[0]) + abs(a[1] - b[1]);
}

public static int[] fun(int[] taxi, int[][] starti, int[][] cilji, int left, int m, int index, int n, int atm) {
    int[] temp1;
    int[] temp2;
    int[] tab = new int[m*2+1];
    int[] min = new int[m*2+1];
    min[m*2] = Integer.MAX_VALUE;

    if (left == 0) {
        return tab;
    }

    for (int i = 0; i < m; i++) {

        if (starti[i] != null && atm < n) { 
            temp1 = starti[i];
            starti[i] = null;

            tab = fun(temp1, starti, cilji, left, m, index+1, n, atm+1);
            tab[index] = i+1;
            tab[m*2] += razdalja(taxi, temp1);
            starti[i] = temp1;

            if (tab[m*2] < min[m*2]) {
                min = tab;
            }

        } 
        else if (cilji[i] != null && starti[i] == null) {
            temp2 = cilji[i];
            cilji[i] = null;

            tab = fun(temp2, starti, cilji, left-1, m, index+1, n, atm-1);
            tab[index] = i+1;
            tab[m*2] += razdalja(taxi, temp2);
            cilji[i] = temp2;

            if (tab[m*2] < min[m*2]) {
                min = tab;
            }

        }



    }

    return min;
}
以上输入的正确输出(这些数字的my函数返回表+表中的最后一个数字是路径的长度)

编辑2: 更重要的是,我注意到一些我可能会改进的地方,但我不确定如何改进。对于函数中的循环,总是迭代所有的i值,即使在很多情况下,它在达到足够高的“i”之前什么都不做,因为starti[i]和cilji[i]对于大多数i值都等于null,一旦我们深入递归。对于每个已经交付的客户,有一个迭代什么也不做


这是两个客户的树的外观: 圆圈坐标是出租车让顾客下车的位置(很明显,我忘了圈出一个)


我已经制定了一个基于动态规划的解决方案,该解决方案在~0.17s的时间内运行,用于最难的测试用例:

INF=10000000000
拾取={}
dest={}
跟踪={}
dp={}
def计算(a、b):
返回abs(a[0]-b[0])+abs(a[1]-b[1])
def解算(curPos,已完成,正在进行):
如果len(已完成)=N且len(正在进行)=0:
返回0
curState=(curPos、冻结集(已完成)、冻结集(正在进行))
如果在dp.keys()中用光标表示:
返回dp[光标状态]
minVal=INF
对于皮卡中的i。键():
如果我已完成:继续
newContinuous=continuous.copy()
newCompleted=completed.copy()
如果我正在进行:
删除(i)
新完成。添加(i)
val=计算(curPos,dest[i])+求解(dest[i],新完成,新进行)
如果val
代码在很多方面都是可以自我理解的,但如果有不清楚的地方,我愿意更详细地解释

编辑:

我们将当前状态定义为我们所在的当前坐标(curPos)、我们已经完成的一组行程(已完成)和仍在进行的一组行程,即我们的客户在车内(正在进行)-这两组行程中的任何行程尚未开始。我使用
frozenset()
是因为python字典不允许使用
set()
作为字典的哈希键的一部分(例如,在我们的例子中是Map、
dp
trace
),因此普通的
set()
必须转换为一个不可变的集,即
frozenset()

存在多个重叠子问题,这是我们使用dp的主要原因。您可以在
Dp.keys()
中存在curState时添加
打印(“Dp Hit:,curState)
,就像我所做的那样:(由于输出行太多而产生运行时错误)。正如您所看到的,Memorization处理了许多我们不需要重新探讨的大型案例。更好地理解关于使用动态规划求解旅行商问题的阅读:


if i in completed
是~O(log(n))查找,因为内部设置是作为自平衡二叉树实现的,是的,如果len(completed)==n
的条件就足够了。刚刚添加了另一半作为精神检查。

欢迎使用SO。请向我们展示您的解决方案,也许有人会对如何重构或提高效率提出建议,这基本上是一个问题,只需添加一些额外的内容
6                      //max customers in car
148,128                //taxi starting coordinates
7                      //number of customers
1,45,199,178,69        //first customer startX,startY,endX,endY
2,54,87,26,83          //and so on...
3,197,147,135,93
4,12,49,61,66
5,91,8,55,73
6,88,42,15,9
7,184,144,31,34
7,3,1,2,6,5,6,7,4,2,5,4,3,1

this means:
pick (customer) 7  (184,144)
pick 3             (197,147)
pick 1                ...
pick 2
pick 6
pick 5
drop 6
drop 7
pick 4
drop 2
drop 5
drop 4
drop 3
drop 1
input:
2
5,5
2
1,3,7,5,7
2,9,2,9,7

output:
1,1,2,2
INF = 100000000000

pickup = {}
dest = {}
trace = {}
dp = {}

def calc(a, b):
    return abs(a[0] - b[0]) + abs(a[1] - b[1])

def solve(curPos, completed, ongoing):
    if len(completed) == N and len(ongoing) == 0:
        return 0
    curState = (curPos, frozenset(completed), frozenset(ongoing))   

    if curState in dp.keys():
        return dp[curState]

    minVal = INF
    for i in pickup.keys():
        if i in completed: continue
        newOngoing = ongoing.copy()
        newCompleted = completed.copy()

        if i in ongoing:
            newOngoing.remove(i)
            newCompleted.add(i)
            val = calc(curPos, dest[i]) + solve(dest[i], newCompleted, newOngoing)
            if val < minVal:
                minVal = val
                trace[curState] = \
                    ("drop " + str(i), (dest[i], newCompleted, newOngoing))
        elif len(ongoing) < maxCustomers:
            newOngoing.add(i)
            val = calc(curPos, pickup[i]) + solve(pickup[i], newCompleted, newOngoing)
            if val < minVal:
                minVal = val
                trace[curState] = \
                    ("pickup " + str(i), (pickup[i], newCompleted, newOngoing))

    dp[curState] = minVal
    return minVal

def path(state):
    stateVar = (state[0], frozenset(state[1]), frozenset(state[2]))
    if stateVar not in trace.keys():
        return
    print (trace[stateVar][0])
    if trace[stateVar][1] != None: 
        return path(trace[stateVar][1])

maxCustomers = int(input())
rstr = input().split(",")
start = (int(rstr[0]), int(rstr[1]))
N = int(input())
for i in range(N):
    line = input().split(",")
    pickup[int(line[0])] = (int(line[1]), int(line[2]))
    dest[int(line[0])] = (int(line[3]), int(line[4]))

print("Total distance travelled: ", solve(start, set(), set()))
path((start, set(), set()))