当前位置:   article > 正文

算法与数据结构 | 基于Python实现的棋盘覆盖问题可视化(分治算法)_python棋盘覆盖问题分治算法

python棋盘覆盖问题分治算法

目录

问题描述

一、什么是分治法(Divide-and-Conquer)?

1.分治法的基本思想

2.分治法的使用场景

二、分治法解决棋盘覆盖问题 

1.数据抽象

2.递归求解 

三、Python实现算法可视化

1.代码实现

2.运行界面


问题描述

在一个2^{k}\times 2^{k}个方格组成的棋盘中,恰有一个方格与其它方格不同,称该方格为一特殊方格,且称该棋盘为一特殊棋盘。在棋盘覆盖问题中,要用图示的4种不同形态的L型骨牌覆盖给定的特殊棋盘上除特殊方格以外的所有方格,且任何2个L型骨牌不得重叠覆盖。

例如:


 对棋盘覆盖有了一个初步理解之后,采用分治法的思想能够很好的解决该问题。

一、什么是分治法(Divide-and-Conquer)?

1.分治法的基本思想

对于一个规模为n的问题,若n很容易解决(n很小)则直接求解,否则将问题划分为k(1<k≤n)个小规模子问题,这些子问题相互独立且与原问题形式相同。对子问题进行递归求解,并将各个子问题的解进行组合合并得到原问题的解。这种算法设计策略被称为分治法。

2.分治法的使用场景

分治算法生成的子问题总是原始问题的较小模式,这为使用递归技术提供了便利。在这种情况下,通过反复使用分而治之的方法,子问题的类型可以与原始问题保持一致,但规模不断缩小,直到子问题可以轻松直接地解决为止。因此递归过程是自然生成的。在算法设计中应用分治算法和递归可以提高效率。分治算法可以解决的问题一般具有以下特点。

1) 该问题的规模缩小到一定的程度就可以容易地解决

2) 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质

3) 利用该问题分解出的子问题的解可以合并为该问题的解

4) 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题


二、分治法解决棋盘覆盖问题 

1.数据抽象

棋盘覆盖问题的已知条件是在一个的棋盘上有一个特殊方格,因此算法的输入可以用来表示棋盘的大小,用(dr, dc)来表示特殊方格在棋盘中的位置。棋盘覆盖问题的输出结果是一个覆盖了L 形骨牌的棋盘,如何表示三个方格被同一个L形骨牌覆盖称为关键,将数据抽象成程序设计语言方便处理的形式,可以直接使用整数来填充表示被同一个L形骨牌覆盖的三个方格。这样就完成了棋盘覆盖问题中输入/输出数据的抽象。

2.递归求解 

将2k x 2k的棋盘划分为2(k-1) x 2(k-1)这样的子棋盘4块,递归填充各个棋子,填充分为四个情况,递归的出口为k=0,也就是子棋盘的方格数为1,递归填充的四种情况:

  1. 如果特殊方格在左上子棋盘,则递归填充左上子棋盘;否则填充左上子棋盘的右下角,将右下角看作特殊方格,然后递归填充左上棋盘。
  2. 如果特殊方格在右上子棋盘,则递归填充右上子棋盘;否则填充右上子棋盘的左下角,将左下角看作特殊方格,然后递归填充右上棋盘。
  3. 如果特殊方格在左下子棋盘,则递归填充左下子棋盘;否则填充左下子棋盘的右上角,将右上角看作特殊方格,然后递归填充左下棋盘。
  4. 如果特殊方格在右下子棋盘,则递归填充右下子棋盘;否则填充右下子棋盘的左上角,将左上角看作特殊方格,然后递归填充右下棋盘。


三、Python实现算法可视化

1.代码实现

mathplotlib实现可视化,tkinter实现人机交互界面。

  1. import tkinter as tk
  2. from matplotlib import image
  3. from matplotlib.pyplot import pause
  4. import numpy as np
  5. cnt = 0
  6. def change_rgb(rgb):
  7. return "#%02x%02x%02x" % rgb
  8. def countboard(board):
  9. global countbox
  10. n = len(board)
  11. n = n*n
  12. countbox = [-1 for x in range(n)]
  13. k = 0
  14. for i in range(len(board)):
  15. for j in range(len(board)):
  16. countbox[k] = board[i][j]
  17. k+=1
  18. countbox = np.unique(countbox)
  19. for i in range(len(board)):
  20. for j in range(len(board)):
  21. for k in range(len(countbox)):
  22. if board[i][j] == countbox[k]:
  23. board[i][j] = k
  24. def drawboard(canvas1, board, startx=50, starty=50, cellwidth=50):
  25. width = 2 * startx + len(board) * cellwidth
  26. height = 2 * starty + len(board) * cellwidth
  27. canvas1.config(width=width, height=height)
  28. global cnt
  29. cnt+=1
  30. for i in range(len(board)):
  31. for j in range(len(board)):
  32. index = board[i][j]
  33. if index != -1:
  34. if index == 0:
  35. color = 'red'
  36. elif index == 1:
  37. color = 'gold'
  38. elif index == 2:
  39. color = 'blue'
  40. elif index == 3:
  41. color = 'green'
  42. elif index <= cnt:
  43. tc = (255-index*12, 255-index*10, index*10)
  44. color = change_rgb(tc)
  45. board[i][j] == -1
  46. else:
  47. color = 'white'
  48. cellx = startx + i * 50
  49. celly = starty + j * 50
  50. canvas1.create_rectangle(cellx, celly, cellx + cellwidth, celly + cellwidth,
  51. fill=color, outline="black")
  52. canvas1.after(1000, drawboard, canvas1, board)
  53. def ChessBoard(tr, tc, dr, dc, size):
  54. global mark
  55. global Board
  56. mark += 1
  57. count = mark
  58. if size == 1:
  59. return
  60. s = size // 2
  61. # 覆盖左上角子棋盘
  62. if dr < tr+s and dc < tc+s:
  63. ChessBoard(tr, tc, dr, dc, s)
  64. else:
  65. Board[tr+s-1][tc+s-1] = count
  66. ChessBoard(tr, tc, tr+s-1, tc+s-1, s)
  67. # 覆盖右上角子棋盘
  68. if dr < tr+s and dc >= tc+s:
  69. ChessBoard(tr, tc+s, dr, dc, s)
  70. else:
  71. Board[tr+s-1][tc+s] = count
  72. ChessBoard(tr, tc+s, tr+s-1, tc+s, s)
  73. # 覆盖左下角子棋盘
  74. if dr >= tr+s and dc < tc+s:
  75. ChessBoard(tr+s, tc, dr, dc, s)
  76. else:
  77. Board[tr+s][tc+s-1] = count
  78. ChessBoard(tr+s, tc, tr+s, tc+s-1, s)
  79. # 覆盖右下角子棋盘
  80. if dr >= tr+s and dc >= tc+s:
  81. ChessBoard(tr+s, tc+s, dr, dc, s)
  82. else:
  83. Board[tr+s][tc+s] = count
  84. ChessBoard(tr+s, tc+s, tr+s, tc+s, s)
  85. def showImage(Board):
  86. n=len(Board)
  87. for i in range(n):
  88. for j in range(n):
  89. print(Board[i][j], end=' ')
  90. print(' ')
  91. def Input():
  92. global Board
  93. global mark
  94. mark = 0
  95. n=entry_board_size.get()
  96. x=entry_board_x.get()
  97. y=entry_board_y.get()
  98. n=2**int(n)
  99. board = np.zeros(shape=[n, n], dtype=int)
  100. Board = [[-1 for x in range(n)] for y in range(n)]
  101. ChessBoard(0, 0, int(x), int(y), n)
  102. countboard(Board)
  103. window_chessboard = tk.Toplevel(window)
  104. window_chessboard.title('Chessboard')
  105. canvas1 = tk.Canvas(window_chessboard, bg="white")
  106. canvas1.pack()
  107. # button = tk.Button(window_chessboard, text="Next", font=('Arial', 15), command = drawboard(canvas1, Board))
  108. # button.pack()
  109. drawboard(canvas1, Board)
  110. showImage(Board)
  111. window = tk.Tk()
  112. window.title('Chessboard Coverage')
  113. window.geometry('800x400')
  114. window.resizable(width=False,height=False)
  115. tk.Label(window, text = 'Chessboard Coverage', font=('Times New Roman',25)).place(x=240,y=50)
  116. tk.Label(window, text = "输入棋盘大小(2的幂指数):",font=('Arial',15)).place(x=70, y=150)
  117. var_board_size = tk.StringVar()
  118. entry_board_size = tk.Entry(window, textvariable=var_board_size, font=('Arial',15))
  119. entry_board_size.place(x=350, y=150)
  120. tk.Label(window, text = "输入特殊方格位置:", font=('Arial',15)).place(x=70,y=200)
  121. tk.Label(window, text = "横坐标x:", font=('Arial',15)).place(x=150,y=250)
  122. var_board_x = tk.StringVar()
  123. entry_board_x = tk.Entry(window, textvariable=var_board_x, font=('Arial',15))
  124. entry_board_x.place(x=230, y=250)
  125. tk.Label(window, text = "纵坐标y:", font=('Arial',15)).place(x=450,y=250)
  126. var_board_y = tk.StringVar()
  127. entry_board_y = tk.Entry(window, textvariable=var_board_y, font=('Arial',15))
  128. entry_board_y.place(x=530, y=250)
  129. btn = tk.Button(window, text = "Run", font=('Arial',15),command = Input).place(x=350,y=300)
  130. window.mainloop()

2.运行界面

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/498692
推荐阅读
相关标签
  

闽ICP备14008679号