projecteuler.net 題目筆記 [15]

題目15:從20*20的網格的左上角通往右下角有多少條路?

從一個2×2網格的左上角開始,有6條(不容許往回走)通往右下角的路。php

 

對於20×20的網格,這樣的路有多少條?python

class NetGame():
    """丟入一個n X n格的網絡
    說明: x:橫座標, y:縱座標   如(x,y)表示 數組net[y][x]
    """
    def __init__(self,cell=None):       # 初始化網絡 ,從左上角開始,到右下角,只能向右/向下方向前進
        if not cell:raise KeyError
        self.net = [[0 for i in range(cell+1)] for j in range(cell+1)]  # 創建二維座標網絡
        self.length = cell+1            # 長度
    def check_next(self,x,y):
        """檢測下一步能夠向哪方向走
        {'down':True,'right':False}
        """
        arrow = {'down':True,'right':True}
        if y >= self.length-1:
            arrow['down'] = False
        if x >= self.length-1:
            arrow['right'] = False
        return arrow
    def go_down(self,x,y):
        # 傳入向下走一步, 返回座標
        return (x,y+1)
    def go_right(self,x,y):
        # 向右走一步
        return (x+1,y)
    def check_end(self,x,y):
        """檢查座標是否已經到終點"""
        if (x,y) == (self.length-1, self.length-1):
            return True
        return False
    def run_from_xy(self,x,y ):
        """從當前座標(x,y) 開始向座標(n-1,n-1)終點行走,返回可能的路線.
        """
        path_list = [(x,y)]     # 收集途經座標,第一個是起點座標
        def running(path_list):
            x,y = path_list[-1]     # 最後一個座標
            if self.check_end(x,y):
                yield path_list
            arrow = self.check_next(x,y)
            for direction,TF in arrow.iteritems():
                if TF:    # 哪一個方向能夠走, 設置爲1
                    go_func = eval('self.go_%s' % direction)     # 套入go_down,go_right
                    new_x,new_y = go_func(x,y)          # 取得下一步的座標 在這裏 x,y=go_func(x,y) 吃了大虧!!
                    path_list_new = path_list[:]
                    path_list_new.append((new_x,new_y))     # 將座標加入路徑列表
                    for i in running(path_list_new):
                        yield i
        return running(path_list)
    def run(self):
        """從(0,0)座標開始行走,返回通過座標的列表"""
        return self.run_from_xy(0,0)
    @property
    def count(self):
        """列出全部路線之和,從(0,0)開始"""
        count_cnt = 0
        for ele in self.run():
            count_cnt += 1
        return count_cnt
    def list_array(self):
        """列出全部線路的二維數組"""
        import copy
        for coordinate in self.run():   # 返回座標列表
            net = copy.deepcopy(self.net)
            for x,y in coordinate:
                net[y][x] = 1
            yield net

彷佛能夠作成機器人走走的算法. 算法



首先驗證一下題目數組

import time
t1 = time.time()
net = NetGame(cell=2)
print "通過的線路座標:"
cnt = 0
for e in net.run():
    print e
    cnt+=1
print "路線數:",cnt
t2 = time.time()
print "共用時間:",t2-t1

print "全部的線路二維座標:"
for i in net.list_array():
    print i

通過的線路座標:網絡

[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)]app

[(0, 0), (0, 1), (1, 1), (1, 2), (2, 2)]spa

[(0, 0), (0, 1), (1, 1), (2, 1), (2, 2)].net

[(0, 0), (1, 0), (1, 1), (1, 2), (2, 2)]code

[(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)]orm

[(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)]

路線數: 6

共用時間: 0.0


全部的線路二維座標:

[[1, 0, 0], [1, 0, 0], [1, 1, 1]]

[[1, 0, 0], [1, 1, 0], [0, 1, 1]]

[[1, 0, 0], [1, 1, 1], [0, 0, 1]]

[[1, 1, 0], [0, 1, 0], [0, 1, 1]]

[[1, 1, 0], [0, 1, 1], [0, 0, 1]]

[[1, 1, 1], [0, 0, 1], [0, 0, 1]]



若是改成10格呢j, 線路列表太多,不輸出了.

import time
t1 = time.time()
net = NetGame(cell=10)
print "路線數:",net.count
t2 = time.time()
print "共用時間:",t2-t1

路線數: 184756

共用時間: 10.503000021


若是是20格呢? 所用時間半個小時也運行不完.  算法不太懂. 先略過



貼上一個很吊的算法:

cache = {}
def countRoutes(m,n):
    if m==0 or n==0:
        return 1
    if (m,n) in cache:
        return cache[(m,n)]
    cache[(m,n)] = countRoutes(m,n-1) + countRoutes(m-1,n)
    return cache[(m,n)]
import time
t1 = time.time()
print countRoutes(20,20)
print time.time()-t1

137846528820

0.0

時間爲0 !!!!!!

相關文章
相關標籤/搜索