2010-12-08 29 views
5

即使世界在Android上一個可愛的小遊戲叫Traffic Jam如何改進我的Traffic Jam遞歸求解器的算法?

我寫了一個遞歸求解:

import copy,sys 
sys.setrecursionlimit(10000) 


def lookup_car(car_string,ingrid): 
    car=[] 
    i=0 
    for row in ingrid: 
    j=0 
    for cell in row: 
     if cell == car_string: 
     car.append([i,j]) 
     j+=1 
    i+=1 
    return car 

#True if up/down False if side to side 
def isDirectionUp(car): 
    init_row=car[0][0] 
    for node in car: 
    if node[0] != init_row: 
     return True 
    return False 

def space_up(car,grid): 
    top_node=car[0] 
    m_space_up = (top_node[0]-1,top_node[1]) 
    if top_node[0] == 0: 
    return -1 
    elif grid[m_space_up[0]][m_space_up[1]] != " ": 
    return -1 
    else: 
    return m_space_up 

def space_down(car,grid): 
    bottom_node = car[-1] 
    m_space_down = (bottom_node[0]+1,bottom_node[1]) 
    if bottom_node[0] == 5 : 
    return -1 
    elif grid[m_space_down[0]][m_space_down[1]] != " ": 
    return -1 
    else: 
    return m_space_down 

def space_left(car,grid): 
    left_node = car[0] 
    m_space_left = (left_node[0],left_node[1]-1) 
    if left_node[1] == 0 : 
    return -1 
    elif grid[m_space_left[0]][m_space_left[1]] != " ": 
    return -1 
    else: 
    return m_space_left 

def space_right(car,grid): 
    right_node = car[-1] 
    m_space_right = (right_node[0],right_node[1]+1) 
    if right_node[1] == 5 : 
    return -1 
    elif grid[m_space_right[0]][m_space_right[1]] != " ": 
    return -1 
    else: 
    return m_space_right 

def list_moves(car,grid): 
    ret =[] 
    if isDirectionUp(car): 
    up = space_up(car,grid) 
    if up != -1: 
     ret.append(("UP",up)) 
    down = space_down(car,grid) 
    if down != -1: 
     ret.append(("DOWN",down)) 
    else: 
    left = space_left(car,grid) 
    if left != -1: 
     ret.append(("LEFT",left)) 
    right = space_right(car,grid) 
    if right != -1: 
     ret.append(("RIGHT",right)) 
    return ret 

def move_car(car_string,move,ingrid): 
    grid = copy.deepcopy(ingrid) 
    car = lookup_car(car_string,grid) 
    move_to = move[1] 
    front = car[0] 
    back = car[-1] 
    if(move[0] == "UP" or move[0] == "LEFT"): 
    grid[back[0]][back[1]] = " " 
    grid[move_to[0]][move_to[1]] = car_string 
    elif(move[0] == "DOWN" or move[0] == "RIGHT"): 
    grid[front[0]][front[1]] = " " 
    grid[move_to[0]][move_to[1]] = car_string 
    return grid 

def is_solution(grid):  
    car = lookup_car("z",grid) 
    if(car[-1] == [2,5]): 
    return True 
    elif space_right(car,grid) == -1: 
    return False 
    else: 
    solgrid = move_car("z",("RIGHT",space_right(car,grid)),grid) 
    return is_solution(solgrid) 

def print_grid(grid): 
    for row in grid: 
    print ''.join(row) 

def solve(grid,solution,depth): 
    global stop 
    global state 
    if grid in state: 
    return 
    else: 
    state.append(grid) 
    if stop: 
    return 
    if is_solution(grid): 
    print_grid(grid) 
    print len(solution) 
    else: 
    for each in "abcdefzhijklm": 
     car = lookup_car(each,grid) 
     moves = list_moves(car,grid) 
     for move in moves: 
     solution.append((each,move)) 
     moved_grid = move_car(each,move,grid) 
     solve(moved_grid,solution,depth) 

stop=False 
state=[] 
recdepth=0 

#grid file using a-w and x means free space, and ' ' means yellow car 
grid=[list(x) for x in file(sys.argv[1]).read().split('\n')[0:-1]] 
solve(grid,[],0) 

WHERE網格是在一個文件中:

abccdd 
abeef 
azzhfi 
jjjhfi 
    kll 
    kmm 

但是,它需要超過8000個移動尋找解決方案,並找不到一個簡單的30移動解決方案。算法有什麼問題?

+0

什麼阻止它進入週期? – 2010-12-08 18:12:28

+3

另外,請考慮http://en.wikipedia.org/wiki/Breadth-first_search和http://en.wikipedia.org/wiki/Depth-first_search之間的差異,看看最適合該問題的是什麼。 – 2010-12-08 18:15:19

+1

問題在於你的solve()函數。你試圖實施什麼樣的搜索算法?假設BFS,看看維基百科關於「廣度優先搜索」的文章,並嘗試將它們的僞代碼更忠實地轉換成python。 – jtdubs 2010-12-08 18:15:24

回答

1

如果搜索空間的分支因子是r,那麼搜索樹中深度爲n的頂點數爲(1-r^n)/(1-r)。即使在r = 2的簡單情況下,最小30步解決方案的問題也會有一個搜索樹,其頂點數大約爲2^30 - 1 = 1,000,000,000。現在,你的分支因素可能會大於2,所以30步的問題離平凡很遠! (a)找到一個更好的代表你的問題(搜索字符串數組是slow)和(b)考慮最佳優先搜索,你可以用啓發式引導你的搜索(例如,黃色汽車離目的地的距離或堵塞黃色汽車道路的汽車數量)。

希望這會有所幫助。

1

這實質上是一個(相對令牌)搜索問題,具有巨大的搜索空間。正如其他人所建議的那樣,請閱讀Depth-first search,然後在Breadth-first search上進行閱讀,當您瞭解其差異時,請閱讀A* Search,並提出一個悲觀的評分函數。

另外,請注意,在這種情況下,您已經知道最終狀態應該是什麼,因此,另一種方法是從兩端搜索並在中間相遇。這應該會大大減少您的搜索空間。

如果還不夠,你可以結合技術!