从一个22网格的左上角开始,有6条(不允许往回走)通往右下角的路。
对于2020的网格,这样的路有多少条?
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)]
[(0, 0), (0, 1), (1, 1), (1, 2), (2, 2)]
[(0, 0), (0, 1), (1, 1), (2, 1), (2, 2)]
[(0, 0), (1, 0), (1, 1), (1, 2), (2, 2)]
[(0, 0), (1, 0), (1, 1), (2, 1), (2, 2)]
[(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 !!!!!!