我的 Python 代码关于这个算法有啥问题?

Posted

技术标签:

【中文标题】我的 Python 代码关于这个算法有啥问题?【英文标题】:What's wrong with my Python code about this algorithm?我的 Python 代码关于这个算法有什么问题? 【发布时间】:2020-03-07 12:18:33 【问题描述】:

有一个游戏。每个人都有一个10*10的棋盘。在游戏开始之前,他们需要在他们的棋盘上放置三个“飞机”。问题是:平面放置有多少种可能性?

这是一架飞机。

这是放置飞机的两种合法方式。平面的放置不能重叠,但可以插入缝隙中。

我的代码如下:

class Plane():
    def __init__(self, x, y, direction):
        self.x = x
        self.y = y
        self.direction = direction
    @property
    def body(self):
        x = self.x
        y = self.y
        if self.direction == "up":
            return[(x-2, y-1), (x-1, y-1), (x, y-1),
                   (x+1, y-1), (x+2, y-1), (x, y-2),
                   (x-1, y-3), (x, y-3), (x+1, y-3)]
        elif self.direction == "down":
            return[(x-2, y+1), (x-1, y+1), (x, y+1),
                   (x+1, y+1), (x+2, y+1), (x, y+2),
                   (x-1, y+3), (x, y+3), (x+1, y+3)]
        elif self.direction == "left":
            return[(x+1, y+2), (x+1, y+1), (x+1, y),
                   (x+1, y-1), (x+1, y-2), (x+2, y),
                   (x+3, y+1), (x+3, y), (x+3, y-1)]
        elif self.direction == "right":
            return[(x-1, y+2), (x-1, y+1), (x-1, y),
                   (x-1, y-1), (x-1, y-2), (x-2, y),
                   (x-3, y+1), (x-3, y), (x-3, y-1)]
    @property
    def check(self):
        global chart
        for x in self.body:
            if x[0]<0 or x[0]>9 or x[1]<0 or x[1]>9 or chart[x[0]][x[1]] != 0:
                return False
        return True

def recursion(plane):
    global chart, plane_list
    if plane.check:
        x = plane.x
        y = plane.y
        plane_list.append(plane)
        chart[x][y] = 2
        for j in plane.body:
            chart[j[0]][j[1]] = 1
        if x!= 9:
            find_plane(x+1, y)
        else:
            find_plane(0, y+1)
        plane_list.remove(plane)
        chart[x][y] = 0
        for j in plane.body:
            chart[j[0]][j[1]] = 0

def find_plane(startx, starty):
    global method_list, chart, plane_list
    if len(plane_list) == 3:
        method_list.append(plane_list)
        return
    if startx == 9 and starty == 9:
        return
    for x in range(10):
        for y in range(10):
            if (x > startx or y > starty) and (chart[x][y] == 0):
                recursion(Plane(x, y, "up"))
                recursion(Plane(x, y, "down"))
                recursion(Plane(x, y, "left"))
                recursion(Plane(x, y, "right"))

if __name__ == "__main__":
    method_list = []
    chart = [[0]*10 for i in [0]*10]
    plane_list = []
    find_plane(0, 0)
    print(method_list)

我有问题:

    这是我最终得到的method_list:

这里的截图不完整。实际上,method_list 由 174631 [] 组成。这让我很困惑,因为我的代码逻辑是只有当平面列表的长度为3时,才会将plane_list添加到method_list中。我不明白为什么 method_list 是由一堆空列表组成的。

    我的答案 174631 是错误的。我在网上搜索了这个问题,找到了这篇文章(中文)。 https://blog.csdn.net/GGN_2015/article/details/91295002

翻译:经过DFS,我们发现9*9飞机轰炸游戏中有8744个放置方案。如果棋盘大小为10×10,则方案总数为66816。

但是我的答案是66816的好几倍。算法我想了很久,还是不知道哪里错了。希望得到答复。

【问题讨论】:

您是否有可能由于对称而多算,例如如果您交换两个“不同”平面的位置,那么这是否算作不同的解决方案,您的算法是否单独计算?最好的调试方法可能是尝试使用较小的输入,您可以手动计算出正确的结果。 【参考方案1】:

我花了一些时间得到了 66816。 我会尽量回答:

1。 整个method_list 是对一个列表的引用列表 - plane_list。 当plane_list 为空时,则method_list 的所有元素都为空... plane_list 是空的,因为您删除了所有元素。 您应该将method_list.append(plane_list) 替换为method_list.append(plane_list.copy())

2。 这段代码背后的逻辑真的很糟糕:

    if x!= 9:
        find_plane(x+1, y)
    else:
        find_plane(0, y+1)

我明白你想在这里做什么,但你做错了。所以......不要这样做。不要试图在 plane_list 中有某种顺序。 就这样做吧:

find_plane(0, 0)

那么您将在method_list 中有重复项: 平面的顺序可以是:(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)。 同一个位置有6个副本。 所以...你应该将 len(method_list) 除以 6。

【讨论】:

以上是关于我的 Python 代码关于这个算法有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章

这个c代码有啥问题?

(permutation/Anagrm) 在 python 2.72 中找到的单词(需要帮助来找出我的代码有啥问题)

这个属性装饰器(python)有啥问题[重复]

网页搜索输入框的这个搜索过滤器代码有啥问题?

这个 Forster-Overfelt 版本的 Greiner-Horman 多边形裁剪算法的伪代码有啥问题?

我的 python 递归快速排序算法有啥问题?