Python bomber游戏算法复杂性优化

Python bomber游戏算法复杂性优化,python,algorithm,optimization,time-complexity,Python,Algorithm,Optimization,Time Complexity,我正在尝试解决以下任务: 二维网格中的每个单元包含一堵墙(“W”)或一个敌人(“E”), 或为空('0')。炸弹可以摧毁敌人,但城墙太坚固了 被摧毁。放在空牢房里的炸弹可以摧毁所有敌人 在同一行和同一列中,但一旦遇到 墙 返回使用一颗炸弹可以摧毁的最大敌人数量 请注意,您的解决方案应该有O(field.length·field[0].length) 复杂性,因为这是面试时会问你的问题 范例 为了 field = [["0", "0", "E", "0"], ["W", "0",

我正在尝试解决以下任务:

二维网格中的每个单元包含一堵墙(“W”)或一个敌人(“E”), 或为空('0')。炸弹可以摧毁敌人,但城墙太坚固了 被摧毁。放在空牢房里的炸弹可以摧毁所有敌人 在同一行和同一列中,但一旦遇到 墙

返回使用一颗炸弹可以摧毁的最大敌人数量

请注意,您的解决方案应该有O(field.length·field[0].length) 复杂性,因为这是面试时会问你的问题

范例

为了

field = [["0", "0", "E", "0"],
         ["W", "0", "W", "E"],
         ["0", "E", "0", "W"],
         ["0", "W", "0", "E"]]
输出应为轰炸机(场)=2

在(0,1)或(0,3)处放置炸弹可摧毁2个敌人

我实现了一个简单的解决方案,但它的复杂性为O(n^2)(n=width*height)。我怎样才能把它送到O(n)?任务被标记为“贪婪”,因此可能有一种贪婪的方法可以工作。 下面是一个简单的解决方案:

def bomber(field):

    if len(field) < 1:
        return 0

    h = len(field)
    w = len(field[0])
    max_enemies = 0

    for row in range(h):
        for col in range(w):

            if field[row][col] == "0":
                cur_max = 0
                cur_row = row
                cur_col = col

                while cur_row >= 0:
                    if field[cur_row][col] == "W":
                        break
                    if field[cur_row][col] == "E":
                        cur_max += 1
                    cur_row -= 1

                cur_row = row    

                while cur_row < h:
                    if field[cur_row][col] == "W":
                        break
                    if field[cur_row][col] == "E":
                        cur_max += 1
                    cur_row += 1

                cur_row = row

                while cur_col >= 0:
                    if field[row][cur_col] == "W":
                        break
                    if field[row][cur_col] == "E":
                        cur_max += 1
                    cur_col -= 1

                cur_col = col

                while cur_col < w:
                    if field[row][cur_col] == "W":
                        break
                    if field[row][cur_col] == "E":
                        cur_max += 1
                    cur_col += 1


                if cur_max > max_enemies:
                    max_enemies = cur_max

    return max_enemies 
def轰炸机(现场):
如果len(字段)<1:
返回0
h=len(字段)
w=len(字段[0])
最大敌人=0
对于范围(h)中的行:
对于范围内的列(w):
如果字段[行][列]=“0”:
cur_max=0
cur_row=行
cur_col=col
当前行>=0时:
如果字段[cur_row][col]=“W”:
打破
如果字段[cur_row][col]=“E”:
cur_max+=1
当前行-=1
cur_row=行
当cur_row=0时:
如果字段[行][当前列]=“W”:
打破
如果字段[行][当前列]=“E”:
cur_max+=1
cur_col-=1
cur_col=col
当电流小于w时:
如果字段[行][当前列]=“W”:
打破
如果字段[行][当前列]=“E”:
cur_max+=1
cur_col+=1
如果cur\u max>max\u敌人:
最大敌人=当前最大敌人
返回最大的敌人

< /代码> 如果你考虑一行,你可以确定,在线性时间内每行中可见多少个敌人(同一行)。

def ranges(c):
    i = 0
    while True:
        while i < len(c) and c[i] == "W":
            i += 1
        if i == len(c):
            return
        start = i
        enemies = 0
        while i < len(c) and c[i] != "W":
            if c[i] == "E":
                enemies += 1
            i += 1
        yield range(start, i), enemies

def enemies(c):
    answer = [0] * len(c)
    for r, enemies in ranges(c):
        for i in r:
            answer[i] = enemies
    return answer
使用这个,我们可以为每一行和每一列构造向量,然后在O(W*H)时间内找到最大值。代码使用了一个技巧:
zip(*grid)
grid
的转置

def best(grid):
    rows = [enemies(c) for c in grid]
    cols = [enemies(c) for c in zip(*grid)]
    return max(rows[i][j] + cols[j][i]
            for i in xrange(len(grid))
            for j in xrange(len(grid[0]))
            if grid[i][j] == '0')
以及一项测试,以确保其正常工作:

field = [["0", "0", "E", "0"],
         ["W", "0", "W", "E"],
         ["0", "E", "0", "W"],
         ["0", "W", "0", "E"]]

print best(field)

如果你考虑一个行,你可以确定,在线性时间内行中每个方块中有多少个敌人(同一行)可见。

def ranges(c):
    i = 0
    while True:
        while i < len(c) and c[i] == "W":
            i += 1
        if i == len(c):
            return
        start = i
        enemies = 0
        while i < len(c) and c[i] != "W":
            if c[i] == "E":
                enemies += 1
            i += 1
        yield range(start, i), enemies

def enemies(c):
    answer = [0] * len(c)
    for r, enemies in ranges(c):
        for i in r:
            answer[i] = enemies
    return answer
使用这个,我们可以为每一行和每一列构造向量,然后在O(W*H)时间内找到最大值。代码使用了一个技巧:
zip(*grid)
grid
的转置

def best(grid):
    rows = [enemies(c) for c in grid]
    cols = [enemies(c) for c in zip(*grid)]
    return max(rows[i][j] + cols[j][i]
            for i in xrange(len(grid))
            for j in xrange(len(grid[0]))
            if grid[i][j] == '0')
以及一项测试,以确保其正常工作:

field = [["0", "0", "E", "0"],
         ["W", "0", "W", "E"],
         ["0", "E", "0", "W"],
         ["0", "W", "0", "E"]]

print best(field)

尝试制作一个与输入大小相同的阵列,记录每个位置的炸弹将水平杀死多少敌人。你能想出如何在O(n)时间内做到这一点吗?接下来,你能对垂直击杀做同样的事情吗?接下来,你能用这两个数组来计算你需要的输出吗?顺便说一句,我看不出这个问题的任何部分,贪婪算法是合适的。据我所知,我想到的解决方案并没有贪婪的成分。试着制作一个与输入大小相同的数组,记录每个位置的炸弹水平杀死多少敌人。你能想出如何在O(n)时间内做到这一点吗?接下来,你能对垂直击杀做同样的事情吗?接下来,你能用这两个数组来计算你需要的输出吗?顺便说一句,我看不出这个问题的任何部分,贪婪算法是合适的。据我所知,我想到的解决方案没有贪婪的组件。下一步:减少空间消耗。在到达每一行时,计算每一行的水平击杀非常简单。如果你保留上一行的垂直杀伤信息,并且只在你撞到墙时更新它,那么你一次只能保留一行的垂直杀伤信息,并且仍然可以在
O(len(grid)*len(grid[0])
time中完成整个算法。另外:你不能在敌人体内放置炸弹。这需要处理。@user2357112谢谢——我在描述中漏掉了(炸弹必须放在空位上)。Fixed@user2357112减少空间的想法似乎很聪明,但我不知道它是如何工作的。你必须扫描每一行/每一列两次,这样每一个方块都能看到两边的敌人,但是我不知道如何在不使用O(WH)空格的情况下合并行和列。我可以看到如何将内存使用减半(通过将by cols数据直接添加到by rows数据中),但我不认为这是你的意思。从第一行开始,计算每个空间中的炸弹会垂直杀死多少敌人。每次向下移动一行时,都要为新旧单元格均为非墙的列保留垂直终止信息。如果下一行将某列置于墙内,则将该列的垂直终止点设置为零。如果下一行的某个列让你从墙中走出来,那么再次计算该列的垂直击杀。下一步:减少空间消耗。在到达每一行时,计算每一行的水平击杀非常简单。如果你保留上一行的垂直杀伤信息,并且只在你撞到墙时更新它,那么你一次只能保留一行的垂直杀伤信息,并且仍然可以在
O(len(grid)*len(grid[0])
time中完成整个算法。另外:你不能在敌人体内放置炸弹。那需要