Use this to learn the idea, then write your own version.
123 4class GridMaster(object):5 def canMove(self, direction):6 pass7 8 def move(self, direction):9 pass10 11 def isTarget(self):12 pass13 14 15import collections16 17 18class Solution(object):19 def findShortestPath(self, master):20 """21 :type master: GridMaster22 :rtype: int23 """24 directions = {'L': (0, -1), 'R': (0, 1), 'U': (-1, 0), 'D': (1, 0)}25 rollback = {'L': 'R', 'R': 'L', 'U': 'D', 'D': 'U'}26 27 def dfs(pos, target, master, lookup, adj):28 if target[0] is None and master.isTarget():29 target[0] = pos30 lookup.add(pos)31 for d, (di, dj) in directions.iteritems():32 if not master.canMove(d):33 continue34 nei = (pos[0]+di, pos[1]+dj)35 adj[pos].add(nei)36 adj[nei].add(pos)37 if nei in lookup:38 continue39 master.move(d)40 dfs(nei, target, master, lookup, adj)41 master.move(rollback[d])42 43 def bi_bfs(adj, start, target):44 left, right = {start}, {target}45 lookup = set()46 steps = 047 while left:48 for pos in left:49 lookup.add(pos)50 new_left = set()51 for pos in left:52 if pos in right: 53 return steps54 for nei in adj[pos]:55 if nei in lookup:56 continue57 new_left.add(nei)58 left = new_left59 steps += 160 if len(left) > len(right): 61 left, right = right, left62 return -1 63 64 start = (0, 0)65 target = [None]66 adj = collections.defaultdict(set)67 dfs(start, target, master, set(), adj)68 if not target[0]:69 return -170 return bi_bfs(adj, start, target[0])71 72 737475class Solution2(object):76 def findShortestPath(self, master):77 """78 :type master: GridMaster79 :rtype: int80 """81 directions = {'L': (0, -1), 'R': (0, 1), 'U': (-1, 0), 'D': (1, 0)}82 rollback = {'L': 'R', 'R': 'L', 'U': 'D', 'D': 'U'}83 84 def dfs(pos, target, master, lookup, adj):85 if target[0] is None and master.isTarget():86 target[0] = pos87 lookup.add(pos)88 for d, (di, dj) in directions.iteritems():89 if not master.canMove(d):90 continue91 nei = (pos[0]+di, pos[1]+dj)92 adj[pos].add(nei)93 adj[nei].add(pos)94 if nei in lookup:95 continue96 master.move(d)97 dfs(nei, target, master, lookup, adj)98 master.move(rollback[d])99 100 def bfs(adj, start, target):101 q = [start]102 lookup = set(q)103 steps = 0104 while q:105 new_q = []106 for pos in q:107 if pos == target:108 return steps109 for nei in adj[pos]:110 if nei in lookup:111 continue112 lookup.add(nei)113 new_q.append(nei)114 q = new_q115 steps += 1116 return -1 117 118 start = (0, 0)119 target = [None]120 adj = collections.defaultdict(set)121 dfs(start, target, master, set(), adj)122 if not target[0]:123 return -1124 return bfs(adj, start, target[0])125