国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

用Python玩燒腦小游戲《一筆畫完》,瞬間闖到100關

開發 后端 開發工具
昨天和朋友出去外面吃飯,吃完飯后朋友打開了一個小程序玩了起來......

昨天和朋友出去外面吃飯,吃完飯后朋友打開了一個小程序玩了起來......

[[247317]]

游戲長這樣

大概玩法是:從地圖中貓的位置開始出發,并且經過所有的格子就算過關。游戲還算挺有意思的,經過我的不斷努力終于過到了 30 來關的樣子。

并且隨著游戲關卡的增加,游戲難度也變得越來越大,過一關需要非常久的時間。

最近也正好在研究算法,就打算看能不能寫個通用的算法來找出每個地圖的解。

哥尼斯堡的"七橋問題"

這個游戲的玩法和哥尼斯堡的"七橋問題"有點類似。

哥尼斯堡的"七橋問題":18 世紀著名古典數學問題之一。在哥尼斯堡的一個公園里,有七座橋將普雷格爾河中兩個島及島與河岸連接起來(如下圖)。是否可能從這四塊陸地中任一塊出發,恰好通過每座橋一次,再回到起點?

當時人們想到的證明方法是把七座橋的走法都列出來一個一個試驗,用排列組合的知識很容易得到七座橋所有的走法大概有 7! = 5040 種,如果真的逐一試驗,會是個很大的工作量。

但數學家歐拉沒有這樣想,歐拉把兩座島和河兩岸抽象成頂點,七座橋抽象成連接每個頂點的七條邊,那么這個問題就能被抽象成下面的圖:

假設每座橋都恰好走過一次,那么對于 A、B、C、D 四個頂點中的每一個頂點,需要從某條邊進入,同時從另一條邊離開,進入和離開頂點的次數是相同的,即每個頂點有多少條進入的邊,就有多少條出去的邊。

也就是說:每個頂點相連的邊是成對出現的,即每個頂點的相連邊的數量必須是偶數。

很明顯,上圖中 A、C、D 三個頂點相連的邊都有 3 條,B 頂點的相連邊為 5 條,都是奇數。因此這個圖無法從一個頂點出發,且恰好走過每座橋一次。

由此次證明,人們又得到了歐拉路關系,要使得一個圖形可以一筆畫完,必須滿足如下兩個條件:

  • 圖形必須是連通的不能有孤立的點。
  • 圖中擁有奇數連接邊的點必須是 0 或 2。

對于一個連通圖,通常把從某結點出發一筆畫成所經過的路線叫做歐拉路。那么這個游戲是不是就是讓我們找到一條歐拉路呢?

對游戲進行抽象

按照上面證明七橋問題的方法,我們可以將游戲的地圖抽象成這樣:

  • 其中 14 號頂點為起點。
  • 頂點和邊的關系在程序中可以刻畫成一個二維列表。
  1. graph = [ 
  2.     [1, 6],    #0 
  3.     [0, 2],    #1 
  4.     [1, 7, 3], #2 
  5.     ... 
  6.     [24, 19]   #25 

graph 列表的***層表示每一個頂點,第二層則是與當前頂點有邊的頂點。

抽象完這張游戲地圖后可以很清楚知道,這游戲并不是讓我們找到一條歐拉路。

因為找到一條歐拉路,需要的是經過每一座橋,且只經過一次,也就是說每個頂點可以被多次經過。

而這個游戲需要的是經過每一個頂點,并不要求走完每一座橋,且頂點只能被經過一次。

哈密頓通路

在研究了七橋問題發現并不能解決這類問題后,我開始向團隊的表哥們請教,其中一個表哥告訴我此類問題叫做哈密頓圖 (這里感謝下團隊的**@xq17**表哥)。

這里說的哈密頓圖,實際上是哈密頓通路的一種特殊情況,指的是:由指定的起點出發,途中經過所有其他頂點且只經過一次 ,***返回起點,稱之為哈密頓回路。如果給定的圖 G 具有哈密頓回路,則稱圖 G 為哈密頓圖。

那么現在目標明確了,這個游戲的解法就是找到某個給定圖的哈密頓通路。

但是問題來了!!!哈密頓通路問題,在上世紀七十年代初,被證明是 NP-hard 問題:

  • 一個復雜問題如果能在多項式時間內解決,那么它便被稱為 P 類問題。
  • 一個復雜問題如果不能確定在多項式時間內解決,那么它便被稱為 NP 類問題。

什么意思呢?就拿質因數分解來說吧:

  • P 類問題:23x37=?
  • NP 類問題:已知 axb=740914799,且 a 和 b 都是質數,求 a 和 b 的值

讓我們來看看這個問題有多復雜:

  • 因為 axb=740914799,且 a 和 b 都是質數
  • 設 P={x|2<=x<740914799/2,x 是質數}
  • 易得 (a,b)∈PxP,即 P 與它自身的笛卡爾積

我們用一種叫做篩法的算法來求一下 P 集合的元素個數:

  1. #! /usr/bin/env python 
  2. # -*- coding: utf-8 -*- 
  3. # Coding with love by Naiquan. 
  4. import math 
  5. import time 
  6. start = time.clock() 
  7. number = int(740914799/2) 
  8. marks_list = [True] * (number + 1) 
  9. marks_list[0] = marks_list[1] = False 
  10. for i in range(2, int(math.sqrt(number)) + 1): 
  11.     j = i 
  12.     t = j 
  13.     # 去掉倍數 
  14.     while j * t <= number: 
  15.         marks_list[j * t] = False 
  16.         t += 1 
  17. elapsed = str(time.clock() - start) 
  18. print marks_list.count(True
  19. print "Time used:" + elapsed 

一共有 19841519 個質數,算了我大概 14 分鐘。

PxP 的元素個數一共有 19841519^2 個,要一個個驗證是否等于 740914799,無疑又是一項很大的工程,這就是典型的 NP 類問題。NP 類問題雖然難,但是可以很快驗證一個給定的答案,是否正確。

比如上面的題,我告訴你答案 a=22229,b=33331,你很快就能驗證答案是否正確了。而 NP-hard 問題則是比 NP 問題更難的問題,例如:圍棋。

也就是說并不能找到一個友好的算法,來解決哈密頓通路問題。

算法設計

雖然找到一個圖的哈密頓通路是 NP 困難的,但是好在游戲中的頂點不算太多,還是可以使用暴力一點的方法實現的,例如:圖的深度優先遍歷法(DFS) 即遞歸和回溯法思想。

算法流程:

①將當前頂點壓入已訪問棧和路徑棧中。

②將與當前頂點相通的頂點列出來。

③隨機選取一個相通的頂點,并判斷此頂點是否在已訪問棧中:

  • 在已訪問棧中則取另一個相通的頂點。
  • 不在則將這個相通的頂點作為當前頂點。
  • 若所有相通的頂點都在已訪問棧中, 則判斷路徑棧是否包含所有頂點。
  • 路徑棧中包含所有頂點,則路徑棧為當前圖的哈密頓通路。
  • 不包含所有頂點則回到父頂點, 并從已訪問棧和路徑棧中刪除。

④反復執行 1~3。

算法實現

上面說過圖的頂點和邊的關系可以用一個二維列表來描述:

  1. graph = [ 
  2.     [1, 6],    #0 
  3.     [0, 2],    #1 
  4.     [1, 7, 3], #2 
  5.     ... 
  6.     [24, 19]   #25 

但是要手動輸入這些頂點和邊的關系還是太麻煩了。仔細想了下,如果每個頂點的上下左右有頂點,就一定與上下左右的頂點有邊。

那么這個二維列表就可以簡化成

  1. graph = [ 
  2.     [1,1,1,1,1,1], 
  3.     [1,0,1,1,0,1], 
  4.     [1,1,1,1,1,1], 
  5.     [1,0,1,1,0,1], 
  6.     [1,1,1,1,1,1], 
  7.     [0,0,0,0,0,0]    #每個1代表一個頂點 1與上下左右的1都有邊 與0則沒有 長寬相等易于編寫代碼 

還可以再簡化成一維列表:

  1. graph = [ 
  2.     '111111'
  3.     '101101'
  4.     '111111'
  5.     '101101'
  6.     '111111'
  7.     '000000' 

簡直機智如我啊!于是我寫了個函數對一維列表進行轉換:

  1. def get_index(i, j, G): 
  2.     num = 0 
  3.     for a in xrange(i): 
  4.         num += G[a].count('0'
  5.     for b in xrange(j): 
  6.         if G[i][b] == '0'
  7.             num += 1 
  8.     return i * len(G) + j - num 
  9. def get_graph(G): 
  10.     G = [list(x) for x in G] 
  11.     EG = [] 
  12.     for i in xrange(len(G)): 
  13.         for j in range(len(G[i])): 
  14.             if G[i][j] == '0'
  15.                 continue 
  16.             side_list = [] 
  17.             if j+1 <= len(G[i]) - 1: 
  18.                 if G[i][j+1] == '1'
  19.                     index = get_index(i, j+1, G) 
  20.                     side_list.append(index
  21.             if j-1 >= 0: 
  22.                 if G[i][j-1] == '1'
  23.                     index = get_index(i, j-1, G) 
  24.                     side_list.append(index
  25.             if i+1 <= len(G) - 1: 
  26.                 if G[i+1][j] == '1'
  27.                     index = get_index(i+1, j, G) 
  28.                     side_list.append(index
  29.             if i-1 >= 0: 
  30.                 if G[i-1][j] == '1'
  31.                     index = get_index(i-1, j, G) 
  32.                     side_list.append(index
  33.             EG.append(side_list) 
  34.     return EG 

而算法的實現用圖的鄰接矩陣則更為方便,因此我寫了一個將上列二位列表轉換成鄰接矩陣形式的函數:

  1. def get_matrix(graph): 
  2.     result = [[0]*len(graph) for _ in xrange(len(graph))]  # 初始化 
  3.     for i in xrange(len(graph)): 
  4.         for j in graph[i]: 
  5.             result[i][j] = 1  # 有邊則為1 
  6.     return result 

主要的 DFS 算法如下:

  1. # graph為圖的鄰接矩陣 used為已訪問棧 path為路徑棧 step為已經遍歷的頂點的個數 
  2. def dfs(graph, path, used, step): 
  3.     if step == len(graph): # 判斷頂點是否被遍歷完畢 
  4.         print path 
  5.         return True 
  6.     else
  7.         for i in xrange(len(graph)): 
  8.             if not used[i] and graph[path[step-1]][i] == 1: 
  9.                 used[i] = True 
  10.                 path[step] = i 
  11.                 if dfs(graph, path, used, step+1): 
  12.                     return True 
  13.                 else
  14.                     used[i] = False  # 回溯 返回父節點 
  15.                     path[step] = -1 
  16.     return False 
  17. def main(graph, v): 
  18.     used = []  # 已訪問棧 
  19.     path = []  # 路徑棧 
  20.     for i in xrange(len(graph)): 
  21.         used.append(False)  # 初始化 所有頂點均未被遍歷 
  22.         path.append(-1)     # 初始化 未選中起點及到達任何頂點 
  23.     used[v] = True          # 表示從起點開始遍歷 
  24.     path[0] = v             # 表示哈密頓通路的***個頂點為起點 
  25.     dfs(graph, path, used, 1) 

完整代碼如下:

  1. #! /usr/bin/env python 
  2. # -*- coding: utf-8 -*- 
  3. # Coding with love by Naiquan. 
  4. def dfs(graph, path, used, step): 
  5.     if step == len(graph): 
  6.         print path 
  7.         return True 
  8.     else
  9.         for i in xrange(len(graph)): 
  10.             if not used[i] and graph[path[step-1]][i] == 1: 
  11.                 used[i] = True 
  12.                 path[step] = i 
  13.                 if dfs(graph, path, used, step+1): 
  14.                     return True 
  15.                 else
  16.                     used[i] = False 
  17.                     path[step] = -1 
  18.     return False 
  19. def main(graph, v): 
  20.     used = [] 
  21.     path = [] 
  22.     for i in xrange(len(graph)): 
  23.         used.append(False
  24.         path.append(-1) 
  25.     used[v] = True 
  26.     path[0] = v 
  27.     dfs(graph, path, used, 1) 
  28. def get_index(i, j, G): 
  29.     num = 0 
  30.     for a in xrange(i): 
  31.         num += G[a].count('0'
  32.     for b in xrange(j): 
  33.         if G[i][b] == '0'
  34.             num += 1 
  35.     return i * len(G) + j - num 
  36. def get_graph(G): 
  37.     G = [list(x) for x in G] 
  38.     EG = [] 
  39.     for i in xrange(len(G)): 
  40.         for j in range(len(G[i])): 
  41.             if G[i][j] == '0'
  42.                 continue 
  43.             side_list = [] 
  44.             if j+1 <= len(G[i]) - 1: 
  45.                 if G[i][j+1] == '1'
  46.                     index = get_index(i, j+1, G) 
  47.                     side_list.append(index
  48.             if j-1 >= 0: 
  49.                 if G[i][j-1] == '1'
  50.                     index = get_index(i, j-1, G) 
  51.                     side_list.append(index
  52.             if i+1 <= len(G) - 1: 
  53.                 if G[i+1][j] == '1'
  54.                     index = get_index(i+1, j, G) 
  55.                     side_list.append(index
  56.             if i-1 >= 0: 
  57.                 if G[i-1][j] == '1'
  58.                     index = get_index(i-1, j, G) 
  59.                     side_list.append(index
  60.             EG.append(side_list) 
  61.     return EG 
  62. def get_matrix(graph): 
  63.     result = [[0]*len(graph) for _ in xrange(len(graph))] 
  64.     for i in xrange(len(graph)): 
  65.         for j in graph[i]: 
  66.             result[i][j] = 1 
  67.     return result 
  68. if __name__ == '__main__'
  69.     map_list = [ 
  70.         '111111'
  71.         '101101'
  72.         '111111'
  73.         '101101'
  74.         '111111'
  75.         '000000' 
  76.     ] 
  77.     G = get_graph(map_list) 
  78.     map_matrix = get_matrix(G) 
  79.     # print map_matrix 
  80.     SP = 14 
  81.     main(map_matrix, SP) 

結束

在實現了功能后,我拿著這個程序成功過到了差不多一百關,然后就玩膩了,哈哈哈哈哈哈哈哈哈

本文參考資料:

  • 七橋問題_百度百科

https://baike.baidu.com/item/七橋問題/2580504?fr=aladdin

  • 哈密頓圖_百度百科

https://baike.baidu.com/item/哈密頓圖/2587317?fr=aladdin

  • 這個數學題我做可以,但世界毀滅了別怪我

https://www.bilibili.com/video/av19009866

  • 基于回溯法尋找哈密頓回路

http://www.cnblogs.com/cielosun/p/5654577.html

 

責任編輯:武曉燕 來源: 唯品會安全應急響應中心
相關推薦

2018-01-03 09:26:56

2018-04-26 14:41:47

機器漢字智能

2012-07-18 14:02:54

銳捷網絡

2018-01-15 13:58:46

架構技術棧微信半月刊

2022-03-24 07:57:58

Python水果忍者游戲

2020-08-04 18:23:37

戴爾

2025-11-10 09:29:54

2022-09-16 00:32:39

SQL數據庫習慣

2024-01-15 07:47:09

井字棋游戲編程練習Python

2023-12-07 08:37:49

TCC模式

2020-11-30 06:20:13

javascript

2012-11-13 10:32:22

2022-04-25 21:50:09

前端JS面試題

2011-05-30 13:27:09

2019-02-21 08:50:09

物聯網互聯網IOT

2021-05-04 16:38:54

Linux數學游戲

2015-03-19 10:12:36

下拉刷新開源組件

2013-08-23 09:37:32

PythonPython游戲Python教程

2018-07-03 16:16:24

營銷

2011-01-13 14:29:54

點贊
收藏

51CTO技術棧公眾號

精品粉嫩超白一线天av| 蜜乳av一区二区| 人与动性xxxxx免费视频| 免费成人看片网址| 中文字幕av高清在线观看| 国产精品毛片久久久| 国产女人18水真多18精品一级做| 日韩有码视频在线| 黄色片免费在线观看视频| 久久大胆人体| 久久精品久久久精品美女| 亚洲电影免费观看高清完整版在线观看| 久久riav二区三区| 最爽无遮挡行房视频在线| 久久一二三区| 欧美xingq一区二区| 亚洲国产一区二区三区在线播| 黄网站在线免费看| 日韩高清国产一区在线| 亚洲精品www| 日韩av电影在线播放| 国内外成人在线视频| 国产精选在线观看91| 精品三级在线观看视频| 香港三级日本三级a视频| 一本一道波多野毛片中文在线| 亚洲影音一区| 午夜精品蜜臀一区二区三区免费 | 久草在线青青草| 成人黄色在线看| 国产日韩精品推荐| 亚洲福利免费| 蜜桃91精品入口| 日韩av一区二区在线| 国产一区二区影视| 999日本视频| www久久久| 91福利精品第一导航| y97精品国产97久久久久久| 欧美日韩精品一区二区三区在线观看| 欧美日韩精品一区二区| 亚洲自拍的二区三区| 国产精品一线天粉嫩av| 国产偷国产偷亚洲清高网站| 天堂影视av| 成人综合婷婷国产精品久久免费| 国产精品中文在线| 天堂资源在线| 欧美日韩一区二区在线观看| 高清不卡一区二区三区| 啊啊啊啊啊啊啊视频在线播放| 影音先锋在线视频| 亚洲一级一级97网| 欧美aaaaa性bbbbb小妇| 亚洲柠檬福利资源导航| 国产超碰在线一区| 亚欧洲精品视频在线观看| 在线观看麻豆蜜桃| 国产精品亚洲午夜一区二区三区| 欧美裸身视频免费观看| 久久久伊人欧美| 无夜福利视频观看| 国产精品久久久久久久久男 | 日本一区免费视频| 97在线视频免费观看完整版| 一本色道久久综合亚洲91| 在线观看麻豆视频| 国产精品国产三级欧美二区 | www亚洲一区| 久久久最新网址| 国产亚洲福利| 日本久久久久亚洲中字幕| 日本不卡高清视频| 青青久久aⅴ北条麻妃| 免费高潮视频95在线观看网站| 青青a在线精品免费观看| 97精品久久久久中文字幕 | 久久国内精品自在自线400部| 在线中文字幕视频观看| 可以在线看的黄色网址| 国产精品久久久久久久久免费高清 | 午夜电影网亚洲视频| 国产精品精品视频一区二区三区| 97人人澡人人爽91综合色| 二区三区不卡| 日韩中文字幕视频| 亚洲一区二区av电影| 成人午夜电影在线观看| 精品国产91洋老外米糕| 亚洲欧洲av在线| 蜜芽tv福利在线视频| 色综合网站在线| 嫩草成人www欧美| 欧美 国产 日本| 国产美女在线精品| 在线观看成人免费| 精品9999| 日本电影一区二区三区| 污视频免费在线观看网站| 九九热视频在线观看| 久久九九全国免费| 国产一区二区三区在线看| 亚州黄色一级| 国产suv精品一区二区三区88区| 欧美日韩免费观看视频| 欧美一级黄色大片| 日韩av资源| 91激情在线视频| 日本在线不卡视频| 精品网站在线| 欧美日韩一区二区三区不卡| 国产成人精品电影久久久| 国产在线一区二区| aaa大片在线观看| 91视频国产精品| 亚洲国产日韩欧美在线| 成人免费在线看片| 一区二区三区中文免费| 色佬视频在线观看| 欧美午夜精品在线| 在线播放毛片| 亚洲综合色激情五月| 亚洲精品综合| 亚洲精品永久www嫩草| 欧美在线不卡一区| 欧美人与动牲性行为| 91久久精品国产91久久性色tv| 亚洲高清久久| 欧美视频综合| 91在线免费视频| 亚洲国产欧美一区二区三区丁香婷| 一级毛片在线播放| 欧美日韩国产精选| 亚洲综合色网| 青青草国产精品| 欧美日韩不卡一区二区| 午夜久久久久| 黑人巨茎大战欧美白妇 | 亚洲美女动态图120秒| 欧美伊人亚洲伊人色综合动图| 久久免费国产视频| 久久美女艺术照精彩视频福利播放| 性一爱一乱一交一视频| 午夜免费日韩视频| 亚洲一区二区三区国产| 欧美一区综合| 中文字幕在线三区| 日本五级黄色片| www.亚洲人.com| 国产精品三级久久久久三级| 黄色在线网站| 精品在线不卡| 久久久久国色av免费看影院| 爱高潮www亚洲精品| 天天看片激情网站| 国产一区二区三区免费不卡| 日韩精品一区二区三区三区免费| 视频国产精品| 久中文字幕一区| 精品动漫一区二区三区在线观看| 久久99久久久久| 波多野结衣在线| 亚洲午夜国产成人av电影男同| www.99精品| 国产精品一卡二卡三卡| 日韩成人在线观看| 337p粉嫩大胆色噜噜噜噜亚洲| 欧美日韩一区二区三区在线电影| 污网站在线观看视频| 久久久国产精品一区| 午夜国产精品视频免费体验区| 精品欧美色视频网站在线观看| av中文字幕av| 欧美一区第一页| 另类的小说在线视频另类成人小视频在线| 538在线视频| 男人插女人下面免费视频| 亚洲福利视频免费观看| 99久久国产综合色|国产精品| 精品在线观看入口| 中文字幕无码精品亚洲资源网久久| 色综合色综合色综合色综合色综合| 在线综合视频| 天天射综合网站| 视频一区亚洲| 日本久久精品电影| 国产精品一品二品| 国产在线观看91一区二区三区| bt在线麻豆视频| 成人www视频网站免费观看| 九色在线视频蝌蚪| www.久草| 亚洲欧美日韩第一区| 欧美老女人在线| 无码日韩精品一区二区免费| 青青草原av在线| 日本在线啊啊| 亚洲日产国产精品| 国产香蕉视频在线看| 中文字幕亚洲色图|