Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.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
Python 优化Knight';让我们在棋盘上游览_Python_Algorithm - Fatal编程技术网

Python 优化Knight';让我们在棋盘上游览

Python 优化Knight';让我们在棋盘上游览,python,algorithm,Python,Algorithm,下面是我的代码 我想解决一个骑士之旅的小问题:在N*N棋盘上找到从a点到B点的最小移动次数 我创建了一个板,并使用了一个简单的算法: 1. add point A to candidate list and start loop: 2. pop first element in candidate list and check it: 3. if end - return counter 4. else - add the candidate 's "sons" to end of ca

下面是我的代码

我想解决一个骑士之旅的小问题:在N*N棋盘上找到从a点到B点的最小移动次数

我创建了一个板,并使用了一个简单的算法:

 1. add point A to candidate list and start loop:
 2. pop first element in candidate list and check it:
 3. if end - return counter
 4. else - add the candidate 's "sons" to end of candidate list
 5. go to step 2 (counter is incremented after all previous level sons are popped)
该算法的工作原理与我预期的一样(在一些测试用例中使用),但速度非常慢:

调用
f=Find_route(20,Tile(4,4),Tile(14,11))
(20是电路板尺寸,Tile(4,4)和Tile(14,11)分别是起始和结束位置)在到达答案之前检查了201590(!!)tiles

我尝试通过使用
sorted(tiles,key=lambda e:abs(e.x-end.x)+abs(e.y-end.y))
对候选列表进行排序来优化它,其中
tiles
是候选列表。这在某些情况下是有效的,但在某些情况下是无用的

有用的案例:

  • f=从459到309(~33%!!)查找路径(20,磁贴(1,4),磁贴(1,10)
  • f=找到从87738到79524(~10%:())的路线(20,磁贴(7,0),磁贴(1,11))
无益案件:

  • f=Find_路线(20,Tile(4,4),Tile(14,11)):从201891到201590
  • f=从2134到2111查找路径(20,磁贴(1,4),磁贴(1,11)
我希望最终得到一个近端案例的列表,从中算法可以确切地知道该做什么(比如5个瓷砖半径),我认为这可能会有所帮助,但我更感兴趣的是如何改进我的
优化列表方法。有什么建议吗


代码

class Tile(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        tmp = '({0},{1})'.format(self.x, self.y)
        return tmp

    def __eq__(self, new):
        return self.x == new.x and self.y == new.y

    def get_horse_jumps(self, max_x , max_y):
        l = [(1,2), (1,-2), (-1,2), (-1,-2), (2,1), (2,-1), (-2,1), (-2,-1)]
        return [Tile(self.x + i[0], self.y + i[1]) for i in l if (self.x + i[0]) >= 0 and (self.y + i[1]) >= 0 and (self.x + i[0]) < max_x and (self.y + i[1]) < max_y]          


class Board(object):
    def __init__(self, n):
        self.dimension = n
        self.mat = [Tile(x,y) for y in range(n) for x in range(n)]

    def show_board(self):
        print('-'*20, 'board', '-'*20)
        n = self.dimension
        s = ''
        for i in range(n):
            for j in range(n):
                s += self.mat[i*n + j].__str__()
            s += '\n'
        print(s,end = '')
        print('-'*20, 'board', '-'*20)


class Find_route(Board):
    def __init__(self, n, start, end):
        super(Find_route, self).__init__(n)
        #self.show_board()
        self.start = start
        self.end = end

    def optimize_list(self, tiles, end):
        return sorted(tiles, key = lambda e : abs(e.x - end.x)+abs(e.y - end.y))

    def find_shortest_path(self, optimize = False):
        counter = 0
        sons = [self.start]
        next_lvl = []
        num_of_checked = 0

        while True:
            curr = sons.pop(0)
            num_of_checked += 1
            if curr == self.end:
                print('checked: ', num_of_checked)
                return counter
            else: # check sons
                next_lvl += curr.get_horse_jumps(self.dimension, self.dimension)
                # sons     <- next_lvl (optimize?)
                # next_lvl <- []
                if sons == []:
                    counter += 1
                    if optimize:
                        sons = self.optimize_list(next_lvl, self.end)
                    else:
                        sons = next_lvl
                    next_lvl = []


optimize = True            
f = Find_route(20, Tile(7,0), Tile(1,11))
print(f.find_shortest_path(optimize))
print(f.find_shortest_path())

我在计算跳转次数时遇到问题,因为我不知道何时增加计数器(可能在每次检查时?),但它似乎至少收敛得更快。此外,对于其他情况(例如
f=Find_route(20,Tile(1,4),Tile(8,17))
)它根本没有改善(不确定是否停止…

不要重新发明轮子

  • 构建一个以分片为顶点的图。如果骑士可以一步从一个分片到另一个分片,则将分片与边连接

  • 使用标准的路径查找算法。宽度优先搜索看起来是在未加权图中寻找最短路径的最佳选择


这就是我打算做的,我认为这应该是一种bfs。我不想构建一个图,因为我认为构建过程会很长,但看到我的运行时,我想我会重新考虑
        if optimize == 2:
            if sons == []:
                #counter += 1
                sons = self.optimize_list(next_lvl, self.end)
            else:
                sons = self.optimize_list(sons + next_lvl, self.end)
        else:
            if sons == []:
                counter += 1
                if optimize == 1:
                    sons = self.optimize_list(next_lvl, self.end)
                else:
                    sons = next_lvl
                next_lvl = []

optimize = 2          
f = Find_route(20, Tile(1,4), Tile(8,18)) # from 103761 to 8 ( optimal!!! )
print(f.find_shortest_path(optimize))
print(f.find_shortest_path())