簡體   English   中英

帶主教的騎士的最小動作

[英]Minimum moves of a knight with bishop

問題是在 n*n 棋盤中,一個騎士從 A 點到 B 點的最小移動(騎士可以在水平方向移動兩步,在垂直方向移動一步,或者在水平方向上垂直移動兩步)。 棋盤上有一個對角線行走的象,除非象死了或者位置是B點,否則騎士不能移動到象受威脅的位置。 騎士可以選擇殺死象(如果它處於它可以前往)並釋放所有先前受到威脅的位置。

我在一次在線評估中得到了這個問題,但只有 15 個測試用例中有 10 個是正確的。 我想我可能需要向隊列中的元組添加一個布爾值,以表明在最新步驟中主教是否還活着,但為時已晚。

我該如何修改?

from collections import deque
import math

n = 5
startRow = 0
startCol = 0
endRow = 4
endCol = 3
bishopRow = 3
bishopCol = 0
from collections import deque
import math
#
# Complete the 'moves' function below.
#
# The function is expected to return an INTEGER.
# The function accepts following parameters:
#  1. INTEGER n
#  2. INTEGER startRow
#  3. INTEGER startCol
#  4. INTEGER endRow
#  5. INTEGER endCol
#  6. INTEGER bishopRow
#  7. INTEGER bishopCol
#
def isBishopAlive(n, bishopRow, bishopCol):
    if bishopRow < n and bishopCol < n:
        return True
    else:
        return False
def moves(n, startRow, startCol, endRow, endCol, bishopRow, bishopCol):
    # Write your code here
    x, y = abs(endRow), abs(endCol)
    res = 0
    moves = ((2,1), (1,2), (-1,2), (-2,1), (-2,-1), (-1,-2), (1,-2), (2,-1))
    visited = []
    queue = deque()
    queue.append((startRow, startCol, 0))
    while queue:
        i, j, steps = queue.popleft()
        if i == x and j == y:
            return res + steps
        for di, dj in moves:
            cr = i + di
            cc = j + dj
            if isBishopAlive(n, bishopRow, bishopCol) == True:
                if abs(cr-bishopRow) == abs(cc-bishopCol):
                    if cc != y and cr != x:
                        continue
                if (cr == bishopRow) and (cc == bishopCol):
                    bishopRow, bishopCol = math.inf, math.inf
            if abs(cr) > n-1 or abs(cc) > n-1:
                continue
            if (cr, cc) in visited:
                continue
            if isBishopAlive(n, bishopRow, bishopCol) == True:
                bishop = True
            else:
                bishop = False
            if ((x-i) * di) > 0 or ((y-j) * dj) > 0:
                queue.append([cr, cc, steps+1])
                visited.append((cr, cc))
    return -1    
    

您的代碼中存在以下問題:

  • 主教永遠不會被捕獲,因為當使用crcc到達那個方塊時,首先將評估if abs(cr-bishopRow) == abs(cc-bishopCol)條件——並發現為真——然后是continue

  • 當主教被捕獲時,您的代碼在查看未捕獲主教的其他路徑時永遠不會將其放回原處。 相反,隊列中的項目應該包括該狀態是否是通過捕獲主教來實現的。

  • visited列表中的項目不表明訪問是否發生在主教還活着的時候。 然而,這很重要,因為如果你先訪問一個方塊時主教還活着,然后在主教被俘時再次訪問它,第二次訪問可能會導致更好的解決方案。 因此,在將正方形標記為已訪問時,將活動狀態包含在元組中。

  • 該代碼允許將crcc負坐標推入隊列。 應該避免這種情況。

  • 這種排除遠離目標的動作過於樂觀:

     if ((xi) * di) > 0 or ((yj) * dj) > 0

    以這個棋盤為例,其中“N”是騎士,“B”是主教,“e”是結束方格:

     ┌───┬───┬───┬───┬───┐ │ │ │ │ │ │ ├───┼───┼───┼───┼───┤ │ │ │ │ │ B │ ├───┼───┼───┼───┼───┤ │ │ │ N │ │ │ ├───┼───┼───┼───┼───┤ │ │ │ │ │ │ ├───┼───┼───┼───┼───┤ │ │ │ │ │ e │ └───┴───┴───┴───┴───┘

    主教必須首先采取行動,然后騎士必須移到最上面一行以獲得最佳解決方案。

    我建議刪除此條件,否則請確保它不太嚴格並且永遠不會排除最佳路徑。

不是問題,但是:

  • res永遠不會被賦值為 0 以外的值:不需要這個變量
  • bishop設置,但從未讀取:不需要此變量(以及它周圍的if...else塊)
  • visited最好是一個集合而不是一個列表,所以有更好的時間復雜度。
  • endRowendCol永遠不會是負數,因此在xy復制它們的絕對值是沒有用的。 只需使用原始參數變量。
  • 當您在將方塊放入隊列時將方塊標記為已訪問時,您還應該在進入循環之前對起始方塊執行相同操作。
  • 有一個嵌套if導致continue 這些if條件可以合並為一個if條件 using and
  • 兩個if在相同的水平的條件,這兩個導致continue可以合並成一個if條件使用or
  • (cr == bishopRow)周圍的括號不是必需的。
  • 您可以通過在執行移動時檢查是否達到目標來節省一些執行時間,而不是等到該移動從隊列中彈出。 這只是意味着您必須進行初始檢查以查看起始位置是否等於結束位置,但這是值得的。

這是一個更正的版本:

def moves(n, startRow, startCol, endRow, endCol, bishopRow, bishopCol):
    if startRow == endRow and startCol == endCol:  # Deal with trivial case
        return 0
    moves = ((2,1), (1,2), (-1,2), (-2,1), (-2,-1), (-1,-2), (1,-2), (2,-1))
    queue = deque()
    queue.append((startRow, startCol, True, 0))  # Include that bishop is alive
    # Let visited be a set. Mark start as visited and include alive-status
    visited = set([(startRow, startCol, True)])
    while queue:
        i, j, alive, steps = queue.popleft()
        for di, dj in moves:
            cr = i + di
            cc = j + dj
            if cr == endRow and cc == endCol:  # When found, don't bother about queuing it
                return steps + 1 # No need for a res variable 
            # Update alive-state, just for current path
            stillalive = alive and (cr != bishopRow or cc != bishopCol)
            # Neither cr/cc should be negative
            if 0 <= cr < n and 0 <= cc < n and (cr, cc, stillalive) not in visited and (
                    not stillalive or abs(cr - bishopRow) != abs(cc - bishopCol)):
                queue.append((cr, cc, stillalive, steps + 1))  # Append alive-status too
                visited.add((cr, cc, stillalive))  # Visited should depend on alive
    return -1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM