每張給定的數字圖片只有2種像素值,即0和255,如下所示:

現給定全黑的一張背景圖,用一支筆可以連續地在上下左右斜對角共8個方向移動,可以允許重複地經過一處。筆經過處像素值會變爲0,即變成白色。如果這樣操作後能得到一張如上所示的數字圖片,則稱該數字圖片可以「一筆完成」。
下面是不能「一筆完成」的數字圖片例子:

因爲要完成“6”中間部分的「白圈」,必須要把「筆」拿起來放到對應的位置移動。
將數字“6”用pandas可視化如下所示,這裏去掉像素值全爲0的部分列:
也就說,需要給定一個程序判斷是否有一堆「0」被一堆「255」圍住,如果是的話,這張數字圖片就是不能「一筆完成」的。我這裏用的辦法是深度搜索,往上下左右4個方向深搜,判斷圖片中有幾堆「0」。如果僅有1堆,那麼這個數字圖片可以「一筆完成」;反之。
代碼
import numpy as np
# 讀取函數,數據都被保存在mnist.npz
def load_data():
data = np.load('./mnist.npz')
X = data['X']
return X
def DFS(X, row, col, visited):
visited[row][col] = 1
if X[row][col] == 255:
return
if row+1 < 28 and visited[row+1][col] == 0:
DFS(X, row+1, col, visited)
if col+1 < 28 and visited[row][col+1] == 0:
DFS(X, row, col+1, visited)
if row-1 >= 0 and visited[row-1][col] == 0:
DFS(X, row-1, col, visited)
if col-1 >= 0 and visited[row][col-1] == 0:
DFS(X, row, col-1, visited)
if __name__ == '__main__':
X = load_data()
# X.shape = (10000, 28, 28)
success = 0 # 可以「一筆完成」的數字圖片總數
for t in range(10000):
blocks = 0 # 數字圖片中存在幾堆「0」
visited = np.zeros((28, 28)) # 標記數組
for i in range(28):
for j in range(28):
if X[t][i][j] == 0 and visited[i][j] == 0:
DFS(X[t], i, j, visited)
blocks += 1
if blocks == 1:
success += 1
print(success)